22.4. Трассировка системных вызовов
22.4. Трассировка системных вызовов
Вы когда-нибудь задумывались о том, какие системные вызовы использует наша программа во время своего выполнения? Если да, то этот пункт как раз для вас. Возможно, пока он только удовлетворит ваше любопытство, но через некоторое время эта информация станет вам по-настоящему необходима.
Проследить, какие системные вызовы использует наша программа, позволяет программа strace. Для ее установки нужно установить пакет strace.
Формат вызова команды strace следующий:
strace [-dffhiqrtttTvxx] [-acolumn] [-eexpr] ... [-ofile] [-ppid] ... [-sstrsize] [-uusername] [command | arg ...]]
Ключи программы перечислены в таблице 22.3.
Ключи командной строки strace Таблица 22.3
Ключ Назначение -с Подсчитывать время, затраченное на каждый вызов и обработку ошибок. В конце трассировки будет представлен подробный отчет -d Выводить отладочные сообщения самой программы strace на стандартный вывод ошибки -f Трассировать дочерние процессы, созданные уже трассируемыми процессами -ff Данная опция применятся только вместе с опцией -o имя_файла. Каждый трассируемый процесс будет записан в файл имя_файла.pid -F Следовать вызовам vfork(). Данную опцию нельзя использовать вместе с опцией -f -h Вывести справку -i Выводить указатель инструкции во время системного вызова -q «Тихий режим». Подавляет вывод некоторых сообщений -r Выводить относительную метку времени для каждого вызова -t Перед каждой строкой выводить текущее время -tt То же, что и -t, но будут выводиться также микросекунды -T Показывать время, потраченное на системный вызов (то есть разницу между временем запуска и временем завершения вызова). Для каждого вызова -v Получение дополнительной информации -V Вывести номер версии strace -X Выводить не-ASCII строки в шестнадцатеричном формате -XX Выводить все строки в шестнадцатеричном формате -a столбец Выровнять возвращаемые вызовами значения в указанном столбце (по умолчанию 40) -e выражение Позволяет задать отслеживаемые события. За более подробной информацией обратитесь к справочной системе -e trace=набор Определить набор отслеживаемых вызовов. Например, trace=open,close,read,write -e trace=file Будут отслеживаться только вызовы для работы с файлами (open, stat, chmod, unlink и т.д.) -e trace=process Отслеживаются вызовы для работы с процессами (fork, exec, wait и др.) -e trace=network Отслеживаются сетевые вызовы -e trace=signal Отслеживаются вызовы для работы с сигналами -e trace=ipc Отслеживаются IPC-вызовы -e abbrev=набор Сокращает вывод каждого члена структуры. Например, abbrev=all или abbrev=none -e verbose=набор Различать структуры различных системных вызовов, по умолчанию verbose=all -e raw=set Выводит не декодированные значения аргументов системных вызовов. Данный аргумент полезен, если вы не доверяете декодированию или хотите знать точное числовое представление аргумента -e signal=набор Определяет набор трассируемых сигналов. По умолчанию signal=all. Вы можете использовать восклицательный знак для отрицания, например, signal=!SIGIO означает, что сигнал SIGIO не будет трассирован -e read=набор Выполнять полный шестнадцатиричный и ASCII-дамп всех прочитанных вызовом read() данных. Например, чтобы видеть все данные, поступающие через дескрипторы 2 и 7, введите read=2,7 -e write=набор То же, что и -e read, но только для записи -o имя_файла Перенаправить вывод программы в указанный файл. Данный файл будет полезен для дальнейшего анализа трассировки -p pid Присоединиться к процессу с PID=pid и начать трассировку -s размер Установить максимальный размер строки (по умолчанию 32). Имена файлов не рассматриваются как строки, поэтому всегда будут напечатаны полностью -S критерий Сортирует вывод гистограммы, которая выводится опцией -с, по заданному критерию: time (время), calls (вызовы), name (имя) и nothing (без сортировки) -u имя_пользователя Запустить программу от имени указанного пользователя. Эта опция будет полезной, если вы, зарегистрировавшись как root, будете проверять корректность работы программы, если бы она была запущена под другим пользователемВы даже не можете себе представить, какие системные вызовы использует такая маленькая программка:
Листинг 22.2. Файл prog.с
#include <stdio.h>
int main() {
printf("Hello ");
return 0;
}
Откомпилируйте эту программу (gcc -o prog prog.c) и запустите strace:
$ strace prog
Вы увидите следующий вывод:
execve("./a.out", ["./а.out"], [/* 21 vars */]) = 0
uname((sys="Linux", node="localhost.localdomain", ...}) = 0
brk(0) = 0x80495b4
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 7
fstat64(7, {st_mode=S_IFREG|0644, st_size=31578, ...}) = 0
old_mmap(NULL, 31578, PROT_READ, MAP_PRIVATE, 7, 0) = 0x40014000
close(7) = 0
open("/lib/i686/libc.so.6", O_RDONLY) =7
read(7, "177ELF111331`u1В4"..., 1024) = 1024
fstat64(7, {st_mode=S_IFREG|0755, st_size=1401027, ...}) = 0
old_mmap(0x42000000, 1264928, PROT_READ|PROT_EXEC, MAP_PRIVATE, 7, 0) = 0x42000000
mprotect(0x4212c000, 36128, PROT_NONE) = 0
old_mmap(0x4212c000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 7, 0x12c000) = 0x4212c000
old_mmap(0x42131000, 15648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42131000
close(7) = 0
munmap(0x40014000, 31578) = 0
brk(0) = 0x80495b4
brk(0x80495e4) = 0x80495e4
brk(0x804a000) = 0x804a000
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000
write(1, "Hello ", 6) =6
munmap(0x40014000, 4096) = 0
_exit(0) = ?
Читать вызовы нужно так:
имя системного вызова = возвращаемое значение
В нашем случае мы вывели на консоль шесть символов, поэтому вызов write() возвратит значение 6.
В случае, если системный вызов завершился неудачно (обычно код ошибки -1), программа strace выводит не только код, но и описание ошибки:
open("/foo/bar", O_RDONLY) = -1 ENOENT (No such file or directory)
Стандартные константы выводятся в их символьном представлении:
open("file.dat", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
Сигналы также выводятся в символьном представлении, например:
sigsuspend([] <unfinished ...>
--- SIGINT (Interrupt) ---
+++ killed by SIGINT +++
Структуры, точнее члены структур, заключаются в фигурные скобки и выводятся в формате имя_члена=значение, например:
lstat("/dev/null", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) =0
Символьные указатели печатаются как строки в С, то есть их значения заключены в двойные кавычки:
read(3, "root::0:0:System Administrator:/"..., 1024) = 422
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Номера системных вызовов
Номера системных вызовов Каждому системному вызову операционной системы Linux присваивается номер системного вызова (syscall number). Этот уникальный номер используется для обращения к определенному системному вызову. Когда процесс выполняет системный вызов из пространства
Производительность системных вызовов
Производительность системных вызовов Системные вызовы в операционной системе Linux работают быстрее, чем во многих других операционных системах. Это отчасти связано с невероятно малым временем переключения контекста. Переход в режим ядра и выход из него являются хорошо
Обработка системных вызовов
Обработка системных вызовов Приложения пользователя не могут непосредственно выполнять код ядра. Они не могут просто вызвать функцию, которая существует в пространстве ядра, так как ядро находится в защищенной области памяти. Если программы смогут непосредственно
Реализация системных вызовов
Реализация системных вызовов Реализация системного вызова в ОС Linux не связана с поведением обработчика системных вызовов. Добавление нового системного вызова в операционной системе Linux является сравнительно простым делом. Тяжелая работа связана с разработкой и
9.2.1. Ограничения системных вызовов
9.2.1. Ограничения системных вызовов Режим ядра защищен от влияния режима пользователя. Одна из таких защит состоит в том, что тип данных, передаваемых между режимами ядра и пользователя, ограничен, легко верифицируется и следует строгим соглашениям.• Длина каждого
9.2.3. Использование системных вызовов
9.2.3. Использование системных вызовов Интерфейс, с которым вам, как программисту, возможно, доведется работать, представляет собой набор оболочек библиотеки С для системных вызовов. В оставшейся части этой книги под системным вызовом будет подразумеваться функция
Обработка прерванных системных вызовов
Обработка прерванных системных вызовов Термином медленный системный вызов (slow system call), введенным при описании функции accept, мы будем обозначать любой системный вызов, который может быть заблокирован навсегда. Такой системный вызов может никогда не завершиться. В эту
22.4. Трассировка системных вызовов
22.4. Трассировка системных вызовов Вы когда-нибудь задумывались о том, какие системные вызовы использует наша программа во время своего выполнения? Если да, то этот пункт как раз для вас. Возможно, пока он только удовлетворит ваше любопытство, но через некоторое время эта
2. Отладка и трассировка.
2. Отладка и трассировка. Ну это совсем банально. Выносим определение операторов за определение класса и ставим там точку останова. Чтобы не тормозило в релиз версии, окружаем слово inline ифдефами.template ‹class T›#ifndef DEBUGinline#endifSmartPointer‹T›::operator T*() { return tObj;}template ‹class T›#ifndef
2.2.2. Ошибки системных вызовов
2.2.2. Ошибки системных вызовов Большинство из нас училось писать программы, которые выполняются по четко намеченному алгоритму. Мы разделяли программу на задачи и подзадачи, и каждая функция решала свою задачу, вызывая другие функции для решения соответствующих подзадач.
2.2.3. Коды ошибок системных вызовов
2.2.3. Коды ошибок системных вызовов Большинство системных вызовов возвращает 0, если операция выполнена успешно, и ненулевое значение — в случае сбоя. (В некоторых случаях используются другие соглашения. Например, функция malloc() при возникновении ошибки возвращает нулевой
Трассировка
Трассировка В прошлом трассировка была тесно связана с протоколированием. Трассировка (tracing) представляла собой метод вставки операторов writeln в начале и в конце функций. Операторы применялись для вывода на экран или в файл таких простых сообщений, как "Вход в функцию X" или
Использование системных вызовов операционной системы MS-DOS
Использование системных вызовов операционной системы MS-DOS Функция Краткое описание bdos вызов системы MS-DOS; используются только регистры DX и AL dosexterr получение значений регистров из системы MS-DOS вызовом 59H FP_OFF возвращает смещение far-указателя FP_SEG возвращает сегмент
Колисниченко Денис Николаевич
Просмотр ограничен
Смотрите доступные для ознакомления главы 👉