Как использовать strace для мониторинга системных вызовов Linux

Программы Linux просят ядро делать некоторые вещи за них. Команда strace выявляет эти системные вызовы. Вы можете использовать их, чтобы понять, как работают программы и почему иногда они не работают.


Ядро и системные вызовы

Какими бы умными они ни были, компьютерные программы не могут делать все сами. Они должны делать запросы, чтобы определенные функции выполнялись за них. Эти запросы поступают в ядро Linux. Обычно программа обращается к библиотеке или другому программному интерфейсу, а библиотека затем делает соответствующий запрос, называемый системным вызовом, к ядру.

Возможность видеть системные вызовы, которые делала программа, и ответы на них может помочь вам понять внутреннюю работу программ, которые вас интересуют или которые вы написали. Именно это и делает программа strace. Он может помочь в устранении неполадок и поиске узких мест.

Это не то же самое, что отладка приложения с помощью такого инструмента, как gdb. Отладочная программа позволяет исследовать внутреннюю работу программы во время ее выполнения. Она позволяет пройти через логику программы и проверить память и значения переменных. Для сравнения, программа strace перехватывает информацию о системных вызовах во время выполнения программы. Когда отслеживаемая программа завершается, strace выводит информацию о системных вызовах в окно терминала.

Системные вызовы обеспечивают всевозможные низкоуровневые функции, такие как действия чтения и записи в файлы, уничтожение процессов и так далее. Список сотен системных вызовов находится на странице syscalls man.

СООБЩЕНИЕ: Отладка с помощью GDB: начало работы

.

Установка strace

Если strace еще не установлен на вашем компьютере, вы можете установить его очень легко.

На Ubuntu используйте эту команду:

sudo apt install strace

На Fedora введите эту команду:

sudo dnf install strace

На Manjaro команда:

sudo pacman -Sy strace

.

Первые шаги с strace

Для демонстрации работы strace мы воспользуемся небольшой программой.  Она не делает многого: Она открывает файл и записывает в него строку текста, и в ней нет никакой проверки ошибок. Это просто быстрый хак, чтобы нам было что использовать с strace.

#includeint main(int argc, char argv[]) {// file handleFILE *fileGeek;// открываем файл с именем "strace_demo. txt", или создайте егоfileGeek = fopen("strace_demo.txt", "w");// запишите какой-нибудь текст в файлfprintf(fileGeek, "Write this to the file" );// закройте файлfclose(fileGeek);// выйдите из программыreturn (0);} // конец main

Мы сохранили это в файл под названием "file-io.c" и скомпилировали его с помощью gcc в исполняемый файл под названием stex, названный "strace example."

gcc -o stex file-io.c

Вызовем из командной строки программу strace и передадим ей имя нашего нового исполняемого файла в качестве процесса, который мы хотим отследить. Мы можем с таким же успехом отследить любую из команд Linux или любой другой двоичный исполняемый файл. Мы используем нашу маленькую программу по двум причинам.

Первая причина заключается в том, что программа strace является многословной. Вывод может быть очень большим. Это замечательно, когда вы используете strace в гневе, но поначалу это может быть подавляющим. Для нашей крошечной программы вывод strace ограничен. Вторая причина заключается в том, что наша программа имеет ограниченную функциональность, а исходный код короткий и простой. Это позволяет легче определить, какие разделы вывода относятся к различным частям внутренней работы программы.

strace ./stex

Мы можем ясно видеть системный вызов write, посылающий текст "Запишите это в файл" в наш открытый файл, и системный вызов exit_group. Это завершает все потоки в приложении и отправляет возвращаемое значение обратно в оболочку.


Фильтрация вывода

Даже в нашей простой демонстрационной программе довольно много вывода. Мы можем использовать опцию -e (выражение). Мы передадим имя системного вызова, который хотим увидеть.

strace -e write ./stex

Вы можете сообщать о нескольких системных вызовах, добавляя их в виде списка, разделенного запятыми. Не включайте пробелы в список системных вызовов.

strace -e close,write ./stex


Отправка вывода в файл

Преимущество фильтрации вывода также является проблемой фильтрации вывода. Вы видите то, что просили увидеть, но не видите ничего другого. И некоторые из этих других результатов могут быть более полезными для вас, чем те, которые вы просили посмотреть.

Иногда удобнее захватить все и искать и прокручивать весь набор результатов. Таким образом, вы случайно не исключите ничего важного. Опция -o (output) позволяет отправить вывод сессии strace в текстовый файл.

strace -o trace-output.txt ./stex

Вы можете использовать команду less для прокрутки списка и поиска системных вызовов или чего-либо другого по имени.

less trace-output.txt

Теперь вы можете использовать все возможности поиска команды less для изучения вывода.

СООБЩЕНИЕ: Как использовать команду less в Linux


Добавление временных меток

Вы можете добавить несколько различных временных меток к выводу. Опция -r (относительные временные метки) добавляет временные метки, которые показывают разницу во времени между началом каждого последующего системного вызова. Обратите внимание, что эти значения времени включают время, затраченное на предыдущий системный вызов, и все остальное, что делала программа до следующего системного вызова.

strace -r ./stex

Временные метки отображаются в начале каждой строки вывода.

Чтобы увидеть количество времени, проведенное в каждом системном вызове, используйте опцию -T (syscall-times). Она показывает продолжительность времени, проведенного в каждом системном вызове.

strace -T ./stex

Продолжительность времени показана в конце каждой строки системного вызова.

Чтобы увидеть время, в которое был вызван каждый системный вызов, используйте опцию -tt (absolute timestamps). Это показывает время "настенных часов" с разрешением в микросекунды.

strace -tt ./stex

Время отображается в начале каждой строки.

.

Отслеживание запущенного процесса

Если процесс, который вы хотите отследить, уже запущен, вы все равно можете подключить к нему strace. Для этого вам нужно знать идентификатор процесса. Вы можете использовать ps с grep, чтобы найти его. У нас запущен Firefox. Чтобы узнать ID процесса firefox, мы можем использовать ps и передать его через grep.

ps -e | grep firefox

Мы видим, что ID процесса равен 8483. Мы будем использовать опцию -p (ID процесса), чтобы указать strace, к какому процессу прикрепляться. Обратите внимание, что вам нужно использовать sudo :

sudo strace -p 8483

Вы увидите уведомление о том, что strace присоединился к процессу, а затем вызовы системной трассировки будут отображаться в окне терминала, как обычно.


Создание отчета

Опция -c (только сводка) заставляет strace печатать отчет. Он создает таблицу с информацией о системных вызовах, которые были сделаны трассируемой программой.

strace -c ./stex

Столбцы:

  • % time: процент времени выполнения, потраченный на каждый системный вызов.
  • seconds: общее время, выраженное в секундах и микросекундах, потраченное на каждый системный вызов.
  • usecs/call: Среднее время в микросекундах, затраченное на каждый системный вызов.
  • calls: Количество раз, когда каждый системный вызов был выполнен.
  • errors: Количество сбоев для каждого системного вызова.
  • syscall: Имя системного вызова.

Для тривиальных программ, которые быстро выполняются и завершаются, эти значения будут показывать нули. Реальные значения показаны для программ, которые делают что-то более значимое, чем наше демонстрационное приложение.


Глубокое понимание, легко

Вывод strace может показать вам, какие системные вызовы выполняются, какие из них выполняются многократно, и сколько времени на выполнение тратится в коде на стороне ядра. Это отличная информация. Часто, когда вы пытаетесь понять, что происходит внутри вашего кода, легко забыть, что ваш двоичный файл практически постоянно взаимодействует с ядром для выполнения многих своих функций.

Используя strace, вы видите полную картину.

Ваше имя: *
Ваш e-mail: *
Код: Кликните на изображение чтобы обновить код, если он неразборчив
Введите код: