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

Стилизованное окно терминала на портативном компьютере.Фатмавати ачмад дзэнури / Shutterstock.com

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

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

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

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

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

Системные вызовы предоставляют всевозможные низкоуровневые функции, такие как операции чтения и записи в файлах, завершающие процессы и т. Д. Есть список из сотен системных вызовов на страница руководства по системным вызовам.

Установка strace

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

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

sudo apt install strace

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

sudo dnf установить strace

На Манджаро команда:

sudo pacman -Sy strace

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

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

# включить int main (int argc, char argv[]) {// дескриптор файла FILE * fileGeek; // открыть файл с именем «strace_demo.txt» или создать его fileGeek = fopen («strace_demo.txt», «w»); // записываем текст в файл fprintf (fileGeek, «Записываем это в файл»); // закрываем файл fclose (fileGeek); // выход из программы return (0); } // конец основного

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

gcc -o stex файл-io.c

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

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

strace ./stex

Мы ясно видим, как системный вызов write отправляет текст «Write this to the file» в наш открытый файл и системный вызов exit_group. Это завершает все потоки в приложении и отправляет возвращаемое значение обратно в оболочку.

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

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

strace -e написать ./stex

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

strace -e закрыть, написать ./stex

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

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

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

strace -o трассировка-output.txt ./stex

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

меньше trace-output.txt

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

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

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

strace -r ./stex

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

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

strace -T ./stex

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

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

strace -tt ./stex

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

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

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

ps -e | grep firefox

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

sudo strace -p 8483

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

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

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

strace -c ./stex

Столбцы:

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

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

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

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

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

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *