Завершение процесса - переход от списка allproc к списку zombieproc - PullRequest
1 голос
/ 08 марта 2011

Как процесс прекращается? Допустим, у процесса есть три потока A, B и C. Теперь, когда мы отправляем сигнал SIG_KILL процессу. Пока все хорошо, теперь у каждого процесса есть поле состояния выхода в своей структуре! Итак, когда процессу отправляется сигнал уничтожения, я понимаю, что он отправляется всем потокам. Поток уничтожается либо когда он попадает в ядро. Если это происходит в ядре, оно завершает работу при выходе из ядра. Если поток спит, он выходит, когда просыпается. Правильно ли мое понимание или я что-то неправильно понимаю / упускаю?

Если мое понимание верно, когда процесс заносится в список зомби? когда все потоки вышли или как только он получит сигнал уничтожения?

Ответы [ 2 ]

2 голосов
/ 08 марта 2011

Допустим, процесс имеет три потока A, B и C.

Ok. Я предполагаю, что современный Linux с поддержкой потоков ядра (Linux 2.6 + glibc> 2.3)

Тогда процесс (или группа потоков) состоит из 3 потоков (или существует 3 потока с разными tid s и одинаковыми tgid = PID)

Теперь, когда мы отправляем сигнал SIG_KILL процессу.

Итак, вы используете tgid (PID) здесь. Хорошо.

Теперь каждый процесс имеет поле состояния выхода в своей структуре!

Wwwhat? Да, но убийство и выход из группы потоков имеют специальный код, чтобы получить правильный код выхода для официанта. Для убийства, статус выхода - получить из сигнала; для выхода (syscall sys_group_exit) это аргумент syscall.

Итак, когда процессу отправляется сигнал уничтожения, ... он отправляется всем потокам.

номер

В основном могут быть сигналы двух типов:

  1. по всему процессу - он будет доставлен ЛЮБОМУ потоку в процессе
  2. поток (не может назвать его правильно) - который доставляется tid в один поток, а не в другой.

Итак, SIGKILL распространяется на весь процесс, он убьет весь процесс. Поставляется в какую-то ветку.

Когда ядро ​​доставит этот сигнал - оно вызовет функцию do_group_exit() (http://lxr.linux.no/linux+v2.6.28/kernel/exit.c#L1156, вызванную из http://lxr.linux.no/linux+v2.6.28/kernel/signal.c#L1870), чтобы уничтожить все потоки в группе потоков (в процессе).

Существует zap_other_threads() функция для перебора всех потоков и их уничтожения (с повторной отправкой SIGKILL, доставляемого потоком) http://lxr.linux.no/linux+v2.6.28/kernel/signal.c#L966

когда процесс помещается в список зомби?

После do_exit() вызова функции ядра. В конце строки tsk->state = TASK_DEAD;.

когда все потоки вышли или как только он получит сигнал уничтожения?

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

ОБНОВЛЕНИЕ : все потоки процесса должны быть уничтожены (должны получить сигнал KILL и выполнить очистку), так как они имеют некоторую учетную информацию, которая будет накапливаться в первом потоке (здесь первое упоминание не первое - запускается, но поток, который получил оригинальный SIGKILL для всего процесса, или поток, который называется системным вызовом exit_group). Первый поток должен ждать всех других потоков; и он изменит статус только после этого.

1 голос
/ 10 марта 2011

В FreeBSD процесс-зомби не может выполнить какой-либо код. Следовательно, все, что нуждается в умирающем процессе, чтобы сделать что-то, выполняется до этого момента. Если вы видите процесс в этом состоянии в ps (1) (обычно только в том случае, если он застрял), у него есть обычное состояние, такое как D, S, R или I, с добавлением E (пытается выйти).

Сигнал доставляется одному потоку (конкретному потоку или любому потоку, в зависимости от того, как был сгенерирован сигнал). Акт завершения процесса (действие по умолчанию различных сигналов) имеет глобальный эффект процесса. Одна из вещей, которая происходит, состоит в том, что поток, который был выбран для доставки сигнала (или с именем _exit (2)), запрашивает все другие потоки на выход.

Поток не имеет статуса выхода на уровне ядра; значение, доступное через pthread_join (), является функцией пользовательского пространства.

...