URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 1409
[ Назад ]

Исходное сообщение
"запуск в фоновом режиме"

Отправлено berc , 18-Фев-03 18:12 
Здравствуйте уважаемые Линуксоиды!

  Я тут решил написать некое подобие командного интерпретатора на Си.
Хотелось бы узнать, как следует запускать процесс в фоновом режиме?
В обычном режиме понятно: fork(), exec() и ждем пока потомок завершится,
а тут как?

Буду благодарен любой помощи.

С наилучшими пожеланиями, Ivan


Содержание

Сообщения в этом обсуждении
"RE: запуск в фоновом режиме"
Отправлено vnp , 18-Фев-03 22:10 
>Здравствуйте уважаемые Линуксоиды!
>
>  Я тут решил написать некое подобие командного интерпретатора на Си.
>
>Хотелось бы узнать, как следует запускать процесс в фоновом режиме?
>В обычном режиме понятно: fork(), exec() и ждем пока потомок завершится,
>а тут как?

Проше всего:
1. Процесс делает fork и ждет завершения
2. Ребенок делает fork и завершается
3. Внук делает exec

>Буду благодарен любой помощи.
>
>С наилучшими пожеланиями, Ivan



"RE: запуск в фоновом режиме"
Отправлено XMan , 18-Фев-03 23:49 
А зачем такие сложности ? Если фоновый режим (аналог "$cmd &"), то:

1. процесс делает fork и забывает о потомке :)
2. потомок делает exec

Для правильной реализации завершения потомков нужно перехватить сигнал SIGCHLD на свой обработчик (шоб мог орать "процесс PID завершен") либо направить его на SIG_IGN. Кажись так звучат константы.
Если с ожиданием завершения (аналог "$cmd"), то:

1. процесс делает fork и делает wait(pid_потомка)
2. потомок делает exec


"RE: запуск в фоновом режиме"
Отправлено vnp , 19-Фев-03 01:05 
>А зачем такие сложности ? Если фоновый режим (аналог "$cmd &"), то:
>
>
>1. процесс делает fork и забывает о потомке :)
>2. потомок делает exec
>
>Для правильной реализации завершения потомков нужно перехватить сигнал SIGCHLD на свой обработчик
>(шоб мог орать "процесс PID завершен") либо направить его на SIG_IGN.

У нас, похоже, разное представление о простоте. Неправильно написаный
обработчик (а ошибиться в нем -- как два байта переслать) приведет сами
знаете к чему.

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

Применение SIG_IGN к SIGCHLD по (не)счастливой случайности работает с
нынешними версиями ядра линукс, но закладываться на это не стоит. POSIX
объявляет результат неопределенным (см. http://www.faqs.org/faqs/unix-faq/faq/part3/section-13.html).

Вот, собственно, и все о простоте.

>Кажись так звучат константы.
>Если с ожиданием завершения (аналог "$cmd"), то:
>
>1. процесс делает fork и делает wait(pid_потомка)
>2. потомок делает exec



"RE: запуск в фоновом режиме"
Отправлено XMan , 19-Фев-03 16:17 
Так а в схеме:

1. Процесс делает fork и ждет завершения
2. Ребенок делает fork и завершается
3. Внук делает exec

Разве внук потом в зомби не свалится ? Теоретически, он перейдет к родителю, который никаких wait/waitpid делать не будет. После завершения родителя он перейдет к init, который уже все и почистит. То есть, до завершения родителя все его фоновые процессы будут в состоянии зомби. Тоб то, так и так нужно либо на игнорирование вешать сигнал либо на свой обработчик.

Я когда-то давно набросал прозрачный прокси для ньюсов.Там есть обработчик сигнала SIGCHLD. В нем только такая конструкция:

while (waitpid(0,NULL,WNOHANG) == 0);

Вот уже 3-4 года работает :) Система linux-2.2.15pre7, libc6-2.1.3-19


"RE: запуск в фоновом режиме"
Отправлено berc , 19-Фев-03 19:07 
Т.е. это приблизительно так должно выглядеть?

for(;;)
{
..
..
    if((pid = fork()) <0) {
    write(2, "Shell: cannot fork \n",20); exit(1); }

    else if (pid == 0)
    {
        if((pid2 = fork()) <0) {
        write(2, "Shell: cannot fork\n",20); exit(1); }

    else if (pid2 == 0) {
        execve(path, arg, env);

            write(2, "Shell: cannot execute\n", 23);
        }
             else
        exit(0);
    }
}

Что здесь не так?
Запускаем последовательно 2 процесса и после окончания их выполнения видим:

1820 pts/5    00:00:00 a.out
1827 pts/5    00:00:00 a.out <defunct>
1828 pts/5    00:00:00 a.out <defunct>

Т.е. получается, что фоновые процессы выполнились и остались в состоянии зомби. Теперь нужно как-то завершать эти зомби. Это должен непосредственно сам обработчик SIGCHLD делать?


"RE: запуск в фоновом режиме"
Отправлено XMan , 19-Фев-03 19:25 
Ну ты видел мой последний пост ? Там приведен пример обработчика SIGCHLD. И fork у меня один:

pid_t pid=fork();
switch (pid) {
    case -1: ошибка; break;
    case 0: потомок. чего-то даже делает; break;
    default: родитель. забыл о потомке;
};


"RE: запуск в фоновом режиме"
Отправлено vnp , 19-Фев-03 21:15 
>Так а в схеме:
>
>1. Процесс делает fork и ждет завершения
>2. Ребенок делает fork и завершается
>3. Внук делает exec
>
>Разве внук потом в зомби не свалится ? Теоретически, он перейдет к
>родителю, который никаких wait/waitpid делать не будет. После завершения родителя он
>перейдет к init, который уже все и почистит.

Внук сразу перейдет к init. Никаких зомби.

>То есть, до
>завершения родителя все его фоновые процессы будут в состоянии зомби. Тоб
>то, так и так нужно либо на игнорирование вешать сигнал либо
>на свой обработчик.
>
>Я когда-то давно набросал прозрачный прокси для ньюсов.Там есть обработчик сигнала SIGCHLD.
>В нем только такая конструкция:
>
>while (waitpid(0,NULL,WNOHANG) == 0);

которая, строго говоря, не делает ничего сверх того, что достигается
двойным fork. Минусы ее описаны в том же faq. Плюсы возникнут, если
будет делаться анализ кодов завершения -- где придется мучительно и
виртуозно обходить множество грабель.

>
>Вот уже 3-4 года работает :) Система linux-2.2.15pre7, libc6-2.1.3-19

Мои искренние поздравления.