Как процесс может убить себя?

#include<stdlib.h>
#include<unistd.h>
#include<signal.h>

int main(){

    pid_t pid = fork();

    if(pid==0){
            system("watch ls");
    }
    else{
            sleep(5);
            killpg(getpid(),SIGTERM);  //to kill the complete process tree.
    }
    return 0;
}

Терминал:

anirudh@anirudh-Aspire-5920:~/Desktop/testing$ gcc test.c
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ ./a.out
Terminated

в течение первых 5 секунд отображаются выходные данные "watch ls", а затем они прекращаются, потому что я отправляю SIGTERM.

Вопрос: как процесс может убить себя? Я сделал kill(getpid(),SIGTERM);

Моя гипотеза: поэтому во время вызова kill() процесс переключается в режим ядра. Вызов kill отправляет SIGTERM процессу и копирует его в таблицу процессов процесса. когда процесс возвращается в пользовательский режим, он видит сигнал в своей таблице и завершает себя (КАК? Я ДЕЙСТВИТЕЛЬНО НЕ ЗНАЮ) (я думаю, что ошибаюсь (может быть грубая ошибка) где-то в моей гипотезе.. . так что, пожалуйста, просветите меня)

Этот код на самом деле является заглушкой, которую я использую для тестирования других своих модулей проекта. Он выполняет свою работу за меня, и я доволен этим, но у меня возникает вопрос, как на самом деле процесс убивает себя. Я хочу знать пошаговую гипотезу.

заранее спасибо

Анируд Томер


person Durin    schedule 08.01.2011    source источник
comment
Зачем процессу самоуничтожение? Если он решит завершить работу, не вызовет ли он просто exit()?   -  person 341008    schedule 08.01.2011
comment
Как убить то, в чем нет жизни???   -  person ta.speot.is    schedule 08.01.2011
comment
Причина в приведенном выше случае, если вы вызываете exit() вместо kill, тогда уничтожается только родительский процесс. Дочерний процесс становится сиротой, а init становится его новым родителем и продолжает работать.   -  person Durin    schedule 08.01.2011
comment
Я хочу, чтобы все дерево процессов было завершено. если я использую killpg(pid,SIGTERM), у меня это не работает, и он убивает только дочерний элемент, и снова процесс функции system() продолжает работать. Я попытался выполнить команду killpg(getpid(),SIGTERM), и она сработала за меня. Но опять же вопрос, как это возможно?   -  person Durin    schedule 08.01.2011
comment
Возможно, вам следует отредактировать свой вопрос, чтобы спросить, как убить все дерево процессов, поскольку это, похоже, то, что вы действительно хотите.   -  person dthorpe    schedule 08.01.2011
comment
ах! но тогда люди не ответят мне, как возможно, что процесс убивает себя с помощью функции kill(). Я могу получить ответ на вопрос, как убить полное дерево процессов, просмотрев несколько книг/справочных страниц или погуглив, но я хочу узнать гипотезу, лежащую в основе такого поведения, по коду, который я написал.   -  person Durin    schedule 08.01.2011
comment
Он вызывает секретный системный вызов seppuku(2). ;-) Но на самом деле, я не думаю, что управление вернется к процессу, если вы не добавите обработчик SIGTERM с помощью signal(2).   -  person Keith    schedule 08.01.2011


Ответы (5)


Ваш процесс умирает, потому что вы используете killpg(), который отправляет сигнал группе процессов, а не процессу.

Когда вы fork(), дети наследуют от отца, среди прочего, группу процессов. От man fork:

   *  The child's parent process ID is the same as the parent's process ID.

Таким образом, вы убиваете родителя вместе с ребенком.

Если вы сделаете простое kill(getpid(), SIGTERM), то отец убьет ребенка (то есть watching ls), а затем мирно уйдет.

person Andrea Spadaccini    schedule 15.02.2011
comment
Нет, это неправильно. В приведенном выше коде просто замените killpg на kill, и вы увидите, что через 5 секунд родитель умирает, а дочерний процесс наследуется процессом инициализации. Сделайте ps -a в то время. Еще одна вещь, которую я делаю неправильно, это killpg(getpid(),SIGTERM);, но поскольку pgid и pid родительского процесса одинаковы, здесь это работает. Также дочерний процесс имеет тот же pgid. он должен был быть killpg(getpgid(getpid()),SIGTERM);, когда BASH разветвляет и запускает дочерний процесс, он изменяет его pgid и делает его равным своему pid, так что даже если дочерний процесс killpg bash остается безопасным. - person Durin; 20.02.2011

поэтому во время вызова kill() процесс переключается в режим ядра. Вызов kill отправляет SIGTERM процессу и копирует его в таблицу процессов процесса. когда процесс возвращается в пользовательский режим, он видит сигнал в своей таблице и завершается (КАК? Я ДЕЙСТВИТЕЛЬНО НЕ ЗНАЮ)

В Linux при возврате из режима ядра в режим пользовательского пространства ядро ​​проверяет, есть ли какие-либо ожидающие сигналы, которые могут быть доставлены. Если они есть, он доставляет сигналы непосредственно перед возвратом в режим пользовательского пространства. Он также может передавать сигналы в другое время, например, если процесс был заблокирован select(), а затем убит, или когда поток обращается к неотображенной области памяти.

person Maxim Egorushkin    schedule 15.02.2011

Я думаю, что когда он видит сигнал SIGTERM в своих таблицах процессов, он сначала убивает свои дочерние процессы (полное дерево, так как я вызвал killpg()), а затем вызывает exit().

Я все еще ищу лучший ответ на этот вопрос.

person Durin    schedule 09.01.2011

kill(getpid(), SIGKILL);  // itself I think

Я протестировал его после fork с случаем 0: и он регулярно завершался из отдельного родительского процесса.

Не знаю, стандартный ли это метод сертификации....

(С помощью моего инструмента psensor я вижу, что использование ЦП возвращается на 34%, как обычный программный код с остановленным счетчиком).

person ivan    schedule 29.08.2014

В Perl это очень просто:

   { 
        local $SIG{TERM} = "IGNORE";
        kill TERM => -$$;
   }

Преобразование в C оставлено читателю в качестве упражнения.

person tchrist    schedule 15.02.2011
comment
откуда взялся Perl между ними?? Однако спасибо, что поделились информацией. Я не знаю Perl, поэтому, может быть, когда я начну с ним работать, я увижу эту штуку, - person Durin; 20.02.2011