KasperskyOS Community Edition 1.3

Работа с процессами и потоками исполнения

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

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

GDB-команды для работы с инфериорами

Для работы с инфериорами нужно использовать следующие GDB-команды:

  • info inferiors

    Выводит список инфериоров. Текущий инфериор отмечается символом *. (Контекст процесса, ассоциированного с текущим инфериором, находится в фокусе отладки.)

  • add-inferior

    Создает инфериор.

  • inferior <номер инфериора>

    Переключает на другой инфериор.

  • attach <PID>

    Привязывает текущий инфериор к процессу с идентификатором PID. Чтобы вывести список процессов, нужно выполнить GDB-команду info os processes.

  • detach

    Отвязывает текущий инфериор от процесса.

Настройка обработки событий жизненного цикла процессов

GDB-сервер ядра сообщает отладчику GDB о наступлении следующих событий:

  1. создание дочернего процесса;
  2. запуск начального потока исполнения дочернего процесса;
  3. завершение процесса.

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

Чтобы настроить обработку событий 1 и 2, нужно использовать следующие GDB-команды:

  • set follow-fork-mode {child|parent}

    Указывает отладчику GDB перейти в контекст дочернего процесса (child) или остаться в контексте родительского процесса (parent) при наступлении события 1. Второй вариант выполняется по умолчанию.

  • set detach-on-fork {on|off}

    Указывает отладчику GDB оставить родительский или дочерний процесс привязанным к инфериору (on) или оставить родительский процесс привязанным к инфериору, а также создать новый инфериор и привязать его к дочернему процессу (off) при наступлении события 1. Первый вариант выполняется по умолчанию. При этом, какой процесс привязан к инфериору (родительский или дочерний), зависит от параметра GDB-команды set follow-fork-mode.

  • set follow-exec-mode {new|same}

    Указывает отладчику GDB создать новый инфериор и привязать его к дочернему процессу (new) или не делать этого (same) при наступлении события 2. Второй вариант выполняется по умолчанию.

Рекомендуется настроить обработку событий 1 и 2 следующим образом:

set follow-fork-mode parent set follow-exec-mode same set detach-on-fork off

Такая конфигурация обеспечивает обработку событий 1 и 2 отладчиком GDB следующим образом:

  • При наступлении события 1 создается новый инфериор, который привязывается к дочернему процессу.
  • При наступлении события 1 родительский процесс остается привязанным к инфериору.
  • При наступлении события 2 не создается новый инфериор для дочернего процесса.

Обработку отладчиком GDB события 2 можно использовать для остановки исполнения программы до передачи управления функции main(), чтобы не применять бесконечный цикл.

Чтобы исполнение программы остановилось при наступлении события 2, нужно использовать следующую GDB-команду:

catch exec

Эта GDB-команда обеспечивает остановку исполнения каждого дочернего процесса, при создании которого было обработано событие 1. Чтобы выполнить остановку исполнения отдельных процессов, нужно использовать следующую GDB-команду:

monitor exec [<имя процесса 1>][, <имя процесса 2>]...

Последующий вызов этой GDB-команды отменяет предыдущий, а ее вызов без параметров означает остановку каждого дочернего процесса, при создании которого было обработано событие 1.

Событие 3 обрабатывается отладчиком GDB только в том случае, если созданы инфериоры, привязанные к завершившимся процессам. При обработке этого события отладчик GDB отвязывает инфериор от завершившегося процесса. Обработку события 3 не требуется настраивать.

GDB-команды для работы с потоками исполнения

Чтобы вывести список потоков исполнения, которые содержатся в процессах, привязанных к инфериорам, нужно выполнить следующую GDB-команду:

info threads

Текущий поток исполнения отмечается символом *. (Контекст текущего потока исполнения находится в фокусе отладки.)

Чтобы перейти в контекст другого потока исполнения, нужно выполнить следующую GDB-команду:

thread <значение Id, полученное вызовом GDB-команды info threads>

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