Процессы прекращаются по одной из трех причин: (a) они достигли конца выполнения (номинальный случай), (b) они содержат необработанное исключение (синхронный сбой) ) или (c) они получили какой-то сигнал, что они не обрабатывают (асинхронный сбой).
Я не уверен, что должно означать (a) - даже если программа возвращается из своей функции main()
, она по-прежнему завершается явным вызовом _exit(2)
(или exit_group(2)
) системный вызов (из кода времени выполнения C, который сначала вызывал main()
). Если он не вызовет _exit()
, он вылетит .
Кроме того, я не вижу разницы между (b) и (c) : они получат сигнал в обоих случаях - который они могут либо поймать, блокировать или игнорировать (кроме SIGKILL
- или SIGSTOP
, но последний не завершит процесс).
Предположим, я хотел разработать программу, которая могла бы отслеживать выполнение другой программы в Linux.
Затем вы должны имитировать то, что делают strace(1)
или gdb(1)
: используйте ptrace(PTRACE_ATTACH)
и т. Д. Например, это будет контролировать только выход процесса, а не все его системные вызовы:
strace -e trace=none -p PID
strace -e trace=exit,exit_group -p PID
Интересна опция PTRACE_O_TRACEEXIT
ptrace(2)
:
The tracee is stopped early during process exit, when registers are still available, allowing the tracer to see where the exit occurred, whereas the normal exit notification is done after the process is finished exiting.
В Linux также имеется интерфейс разъема proc, который позволяет отслеживать процессы, не останавливая и не затрагивая их каким-либо образом. Хотя это работает только как root. Пример программы с использованием интерфейса соединителя proc: forkstat(1)
:
forkstat -e exit # will show all exiting processes
stdbuf -oL forkstat -e exit | grep -m1 PID # will only show when PID exits