- Как найти родительский процесс в Linux
- Как найти идентификатор родительского процесса (PPID) в Linux
- Как найти PPID с помощью команды pstree в Linux
- Как найти PPID с помощью команды ps
- Заключение
- Как получить родительский PID данного процесса в GNU /Linux из командной строки?
- 9 ответов
- Изучаем процессы в Linux
- Содержание
- Введение
- Атрибуты процесса
- Жизненный цикл процесса
- Рождение процесса
- Состояние «готов»
- Состояние «выполняется»
- Перерождение в другую программу
- Состояние «ожидает»
- Состояние «остановлен»
- Завершение процесса
- Состояние «зомби»
- Забытье
- Благодарности
Как найти родительский процесс в Linux
Во время выполнения программы ядро создает процесс, который помогает сохранять детали выполнения программы в системной памяти. Когда программа выполняется, она становится процессом для системы. Итак, мы можем сказать, что процесс — это программа, пока он не выполняется.
Процесс, созданный ядром, известен как » родительский процесс «, а все процессы, производные от родительского процесса, называются » дочерними процессами «. Один процесс может состоять из нескольких дочерних процессов, имеющих уникальный PID, но с одним и тем же PPID.
У новичка может возникнуть вопрос: в чем разница между PID и PPID?
Мы уже обсуждали PID в большинстве наших статей, если вы новичок, не беспокойтесь!
В системах Linux одновременно выполняется несколько процессов. Иногда процесс может иметь один поток (блок выполнения внутри процесса) или несколько потоков. Процессы имеют разные состояния; они могут находиться в состоянии ожидания, готовности или работы. Все дело в том, как пользователь или ядро расставляют приоритеты. Итак, эти процессы идентифицируются уникальными номерами, которые мы называем идентификатором процесса (PID). Уникальные номера для родительских процессов называются PPID, и каждый родительский процесс может иметь несколько дочерних процессов с их уникальными идентификаторами. PID дочерних процессов отличаются, поскольку они представляют собой отдельные исполнительные единицы, но имеют один и тот же идентификатор родительского процесса ( PPID ).
Нам нужен PPID, когда дочерний процесс создает проблемы и не работает должным образом. В этом случае это может повлиять на работу других процессов, а также на систему. Здесь, чтобы остановить непрерывно работающий процесс, необходимо убить его родительский процесс.
Давайте проверим, как мы можем найти PPID:
Как найти идентификатор родительского процесса (PPID) в Linux
У нас есть несколько подходов к поиску PPID запущенного процесса в системах Linux:
- Использование команды «pstree»
- Использование команды «ps»
Как найти PPID с помощью команды pstree в Linux
Команда » pstree » — хороший подход для определения идентификатора родительского процесса (PPID), поскольку она показывает отношения родитель-потомок в древовидной иерархии.
Введите в терминале просто команду » pstree » с параметром » -p «, чтобы проверить, как он отображает все запущенные родительские процессы вместе с их дочерними процессами и соответствующими PID.
Он показывает родительский идентификатор вместе с идентификаторами дочерних процессов.
Давайте рассмотрим пример „Mozilla Firefox“, чтобы получить его PPID вместе с полной иерархией процессов. Выполните в терминале следующую команду:
( grep — это инструмент командной строки, который помогает искать определенную строку)
В упомянутых результатах мы видим, что 3528 — это PPID процесса » Firefox «, а все остальные — дочерние процессы.
Чтобы распечатать в терминале только идентификатор родительского процесса, выполните указанную команду:
Как найти PPID с помощью команды ps
Утилита команды » ps » — это еще один способ обрабатывать информацию из файловой системы » / proc » и отслеживать ее.
С помощью этой команды пользователь также может найти PPID и PID запущенного процесса.
Выполните следующую команду » ps » вместе с параметром » ef «, чтобы отобразить подробную информацию о процессах, включая PPID :
Если вы хотите отобразить PPID определенного процесса с подробностями, выполните указанную команду » ps » с помощью » grep «:
( опция » -f » используется для перечисления деталей процесса)
А чтобы получить только PPID » Firefox «, используйте следующий синтаксис:
Итак, найдите PPID » firefox » с помощью команды:
Заключение
При каждом выполнении программы ядро создает процесс, который загружает детали выполнения в память. Этот созданный процесс известен как родительский процесс, имеющий один или несколько потоков. Каждому процессу ядро автоматически присваивает уникальный PPID и PID.
При работе с системой Linux следует знать PPID запущенных процессов. Проблема с дочерним процессом может повлиять на другие процессы. В таких случаях нам может потребоваться убить родительский процесс.
Идентификаторы PPID запущенных процессов можно определить несколькими способами. Самый простой подход — использовать команду » ps » и » pstree «.
Выше мы видели, как с помощью этих двух командных инструментов можно узнать PPID конкретного процесса.
Источник
Как получить родительский PID данного процесса в GNU /Linux из командной строки?
Решено перед запросом: cat /proc/1111/status | grep PPid
9 ответов
Если PID не передается функции или скрипту, они по умолчанию показывают PPID текущего процесса.
Чтобы использовать псевдоним, необходимо указать PID.
Это одна из тех вещей, которые я изучаю, забываю, переучиваю, повторяю. Но это полезно. Флаг команды pstree показывает дерево с листом в N:
Родительский pid находится в переменной PPID оболочки, поэтому
будет печатать идентификаторы родительских объектов ( PPID ) всех процессов.
Для одного процесса просто передайте PID, например: ps j 1234 .
Чтобы извлечь только значение, отфильтруйте вывод с помощью awk , например:
Чтобы отобразить PID всех родителей, используйте pstree , например:
Чтобы получить родительский PID текущего процесса, используйте echo $$ .
Чтение /proc /$ PID /status. Может быть легко написано:
Немного более сложный пример, который проверяет команду родителя, который начал текущий процесс Изменить команду comm = to cmd = посмотреть полную команду
Вот быстрое решение, которое также должно работать:
Запустите top с любыми параметрами, которые вы хотите, например -u username and -p PID .
И пока работает top , нажмите f , он отобразит список параметров, которые вы хотите отобразить в top , и отображаемые параметры будет отображаться буквами CAPITAL, а параметры, которые или не отображаются, будут отображаться маленькими буквами.
Итак, введя букву перед параметром, вы можете включить или отключить ее. Для идентификатора родительского процесса вы должны ввести b , а затем нажмите Enter , он отобразит PPID в верхнем выпуске.
Источник
Изучаем процессы в Linux
В этой статье я хотел бы рассказать о том, какой жизненный путь проходят процессы в семействе ОС Linux. В теории и на примерах я рассмотрю как процессы рождаются и умирают, немного расскажу о механике системных вызовов и сигналов.
Данная статья в большей мере рассчитана на новичков в системном программировании и тех, кто просто хочет узнать немного больше о том, как работают процессы в Linux.
Всё написанное ниже справедливо к Debian Linux с ядром 4.15.0.
Содержание
Введение
Системное программное обеспечение взаимодействует с ядром системы посредством специальных функций — системных вызовов. В редких случаях существует альтернативный API, например, procfs или sysfs, выполненные в виде виртуальных файловых систем.
Атрибуты процесса
Процесс в ядре представляется просто как структура с множеством полей (определение структуры можно прочитать здесь).
Но так как статья посвящена системному программированию, а не разработке ядра, то несколько абстрагируемся и просто акцентируем внимание на важных для нас полях процесса:
- Идентификатор процесса (pid)
- Открытые файловые дескрипторы (fd)
- Обработчики сигналов (signal handler)
- Текущий рабочий каталог (cwd)
- Переменные окружения (environ)
- Код возврата
Жизненный цикл процесса
Рождение процесса
Только один процесс в системе рождается особенным способом — init — он порождается непосредственно ядром. Все остальные процессы появляются путём дублирования текущего процесса с помощью системного вызова fork(2) . После выполнения fork(2) получаем два практически идентичных процесса за исключением следующих пунктов:
- fork(2) возвращает родителю PID ребёнка, ребёнку возвращается 0;
- У ребёнка меняется PPID (Parent Process Id) на PID родителя.
После выполнения fork(2) все ресурсы дочернего процесса — это копия ресурсов родителя. Копировать процесс со всеми выделенными страницами памяти — дело дорогое, поэтому в ядре Linux используется технология Copy-On-Write.
Все страницы памяти родителя помечаются как read-only и становятся доступны и родителю, и ребёнку. Как только один из процессов изменяет данные на определённой странице, эта страница не изменяется, а копируется и изменяется уже копия. Оригинал при этом «отвязывается» от данного процесса. Как только read-only оригинал остаётся «привязанным» к одному процессу, странице вновь назначается статус read-write.
Состояние «готов»
Сразу после выполнения fork(2) переходит в состояние «готов».
Фактически, процесс стоит в очереди и ждёт, когда планировщик (scheduler) в ядре даст процессу выполняться на процессоре.
Состояние «выполняется»
Как только планировщик поставил процесс на выполнение, началось состояние «выполняется». Процесс может выполняться весь предложенный промежуток (квант) времени, а может уступить место другим процессам, воспользовавшись системным вывозом sched_yield .
Перерождение в другую программу
В некоторых программах реализована логика, в которой родительский процесс создает дочерний для решения какой-либо задачи. Ребёнок в данном случае решает какую-то конкретную проблему, а родитель лишь делегирует своим детям задачи. Например, веб-сервер при входящем подключении создаёт ребёнка и передаёт обработку подключения ему.
Однако, если нужно запустить другую программу, то необходимо прибегнуть к системному вызову execve(2) :
или библиотечным вызовам execl(3), execlp(3), execle(3), execv(3), execvp(3), execvpe(3) :
Все из перечисленных вызовов выполняют программу, путь до которой указан в первом аргументе. В случае успеха управление передаётся загруженной программе и в исходную уже не возвращается. При этом у загруженной программы остаются все поля структуры процесса, кроме файловых дескрипторов, помеченных как O_CLOEXEC , они закроются.
Как не путаться во всех этих вызовах и выбирать нужный? Достаточно постичь логику именования:
- Все вызовы начинаются с exec
- Пятая буква определяет вид передачи аргументов:
- l обозначает list, все параметры передаются как arg1, arg2, . NULL
- v обозначает vector, все параметры передаются в нуль-терминированном массиве;
- Далее может следовать буква p, которая обозначает path. Если аргумент file начинается с символа, отличного от «/», то указанный file ищется в каталогах, перечисленных в переменной окружения PATH
- Последней может быть буква e, обозначающая environ. В таких вызовах последним аргументом идёт нуль-терминированный массив нуль-терминированных строк вида key=value — переменные окружения, которые будут переданы новой программе.
Семейство вызовов exec* позволяет запускать скрипты с правами на исполнение и начинающиеся с последовательности шебанг (#!).
Есть соглашение, которое подразумевает, что argv[0] совпадает с нулевым аргументов для функций семейства exec*. Однако, это можно нарушить.
Любопытный читатель может заметить, что в сигнатуре функции int main(int argc, char* argv[]) есть число — количество аргументов, но в семействе функций exec* ничего такого не передаётся. Почему? Потому что при запуске программы управление передаётся не сразу в main. Перед этим выполняются некоторые действия, определённые glibc, в том числе подсчёт argc.
Состояние «ожидает»
Некоторые системные вызовы могут выполняться долго, например, ввод-вывод. В таких случаях процесс переходит в состояние «ожидает». Как только системный вызов будет выполнен, ядро переведёт процесс в состояние «готов».
В Linux так же существует состояние «ожидает», в котором процесс не реагирует на сигналы прерывания. В этом состоянии процесс становится «неубиваемым», а все пришедшие сигналы встают в очередь до тех пор, пока процесс не выйдет из этого состояния.
Ядро само выбирает, в какое из состояний перевести процесс. Чаще всего в состояние «ожидает (без прерываний)» попадают процессы, которые запрашивают ввод-вывод. Особенно заметно это при использовании удалённого диска (NFS) с не очень быстрым интернетом.
Состояние «остановлен»
В любой момент можно приостановить выполнение процесса, отправив ему сигнал SIGSTOP. Процесс перейдёт в состояние «остановлен» и будет находиться там до тех пор, пока ему не придёт сигнал продолжать работу (SIGCONT) или умереть (SIGKILL). Остальные сигналы будут поставлены в очередь.
Завершение процесса
Ни одна программа не умеет завершаться сама. Они могут лишь попросить систему об этом с помощью системного вызова _exit или быть завершенными системой из-за ошибки. Даже когда возвращаешь число из main() , всё равно неявно вызывается _exit .
Хотя аргумент системного вызова принимает значение типа int, в качестве кода возврата берется лишь младший байт числа.
Состояние «зомби»
Сразу после того, как процесс завершился (неважно, корректно или нет), ядро записывает информацию о том, как завершился процесс и переводит его в состояние «зомби». Иными словами, зомби — это завершившийся процесс, но память о нём всё ещё хранится в ядре.
Более того, это второе состояние, в котором процесс может смело игнорировать сигнал SIGKILL, ведь что мертво не может умереть ещё раз.
Забытье
Код возврата и причина завершения процесса всё ещё хранится в ядре и её нужно оттуда забрать. Для этого можно воспользоваться соответствующими системными вызовами:
Вся информация о завершении процесса влезает в тип данных int. Для получения кода возврата и причины завершения программы используются макросы, описанные в man-странице waitpid(2) .
Передача argv[0] как NULL приводит к падению.
Бывают случаи, при которых родитель завершается раньше, чем ребёнок. В таких случаях родителем ребёнка станет init и он применит вызов wait(2) , когда придёт время.
После того, как родитель забрал информацию о смерти ребёнка, ядро стирает всю информацию о ребёнке, чтобы на его место вскоре пришёл другой процесс.
Благодарности
Спасибо Саше «Al» за редактуру и помощь в оформлении;
Спасибо Саше «Reisse» за понятные ответы на сложные вопросы.
Они стойко перенесли напавшее на меня вдохновение и напавший на них шквал моих вопросов.
Источник