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

Исходное сообщение
"Вызов fork и процессы"

Отправлено Bushi , 03-Мрт-04 09:02 
Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по rsh снимает статистику с маршрутизатора. Для этого главный процесс создает pipe, процесс форкается, затем стандартный поток вывода в дочернем процессе перенаправляется в pipe и с помощью вызова exec запускается утилита rsh, которая в стандартный поток вывода выдает информацию. Затем дочерний процесс естественно закрывается.
Но при вызове ps видно все дочерние процессы.
# ps -waux | grep cbir
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
.................
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
cbir       0  0,0  0,0     0    0  ??  ZW   -         0:00,00  (rsh)
cbir   57939  0,0  0,2  2792 1372  ??  Is   10:27     0:00,00 /usr/local/sbin/cbir

в чем дело? Откуда эта информация? Ведь все дочерние процессы завершили свою работу?


Содержание

Сообщения в этом обсуждении
"Вызов fork и процессы"
Отправлено vnp , 03-Мрт-04 20:47 
>Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по rsh снимает
>статистику с маршрутизатора. Для этого главный процесс создает pipe, процесс форкается,
>затем стандартный поток вывода в дочернем процессе перенаправляется в pipe и
>с помощью вызова exec запускается утилита rsh, которая в стандартный поток
>вывода выдает информацию. Затем дочерний процесс естественно закрывается.
>Но при вызове ps видно все дочерние процессы.
># ps -waux | grep cbir
>cbir       0  0,0  0,0 0    0  ?? ZW   -  0:00,00  (rsh)
[...]
>в чем дело? Откуда эта информация? Ведь все дочерние процессы завершили свою
>работу?

Обратите внимание на флажки состояния Z и W. Если внимательно прочитать man ps, то можно узнать, что процесс стал зомби, и останется таковым, пока родитель не вызовет wait(). Борются с этим либо ловлей SIGCHLD, либо двойным форком.



"Вызов fork и процессы"
Отправлено Bushi , 04-Мрт-04 08:48 
>>Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по rsh снимает
>>статистику с маршрутизатора. Для этого главный процесс создает pipe, процесс форкается,
>>затем стандартный поток вывода в дочернем процессе перенаправляется в pipe и
>>с помощью вызова exec запускается утилита rsh, которая в стандартный поток
>>вывода выдает информацию. Затем дочерний процесс естественно закрывается.
>>Но при вызове ps видно все дочерние процессы.
>># ps -waux | grep cbir
>>cbir       0  0,0  0,0 0    0  ?? ZW   -  0:00,00  (rsh)
>[...]
>>в чем дело? Откуда эта информация? Ведь все дочерние процессы завершили свою
>>работу?
>
>Обратите внимание на флажки состояния Z и W. Если внимательно прочитать man
>ps, то можно узнать, что процесс стал зомби, и останется таковым,
>пока родитель не вызовет wait(). Борются с этим либо ловлей SIGCHLD,
>либо двойным форком.


Спасибо за ответ! С помощью wait проблема решена. А что такое двойной форк? Можете объяснить?


"Вызов fork и процессы"
Отправлено vnp , 04-Мрт-04 10:32 
>Спасибо за ответ! С помощью wait проблема решена. А что такое двойной
>форк? Можете объяснить?

Идея в следующем: Родитель должен ждать завершения потомка. Если родитель завершился первым, заботы о потомке берет на себя init. Если потомки порождаются и заканчиваются непредсказуемо и независимо друг от друга, бывает полезна такая модель:

if((pid = fork()) > 0) {
   waitpid(pid, ...);
} else {
    if(fork() > 0) {
        exit(0);
    } else {
        exec...
    }
}

В такой редакции "первый потомок" завершается немедленно, т.е. wait() не блокируется, и не надо заморачиваться с portability issues вокруг SIGCHLD.


"Вызов fork и процессы"
Отправлено Bushi , 04-Мрт-04 10:34 
>Идея в следующем: Родитель должен ждать завершения потомка. Если родитель завершился первым,
>заботы о потомке берет на себя init. Если потомки порождаются и
>заканчиваются непредсказуемо и независимо друг от друга, бывает полезна такая модель:
>
>
>if((pid = fork()) > 0) {
>   waitpid(pid, ...);
>} else {
>    if(fork() > 0) {
>        exit(0);
>    } else {
>        exec...
>    }
>}
>
>В такой редакции "первый потомок" завершается немедленно, т.е. wait() не блокируется, и
>не надо заморачиваться с portability issues вокруг SIGCHLD.


Спасибо, идею понял.


"Вызов fork и процессы"
Отправлено dmi , 29-Мрт-04 18:01 
Если следовать теории что после каждого раздвоения процесса надо ждать завершения процесса-потомка, то значит ли это что никакой многозадачности не может быть впринципе?

"Вызов fork и процессы"
Отправлено Bushi , 29-Мрт-04 18:56 
>Если следовать теории что после каждого раздвоения процесса надо ждать завершения процесса-потомка,
>то значит ли это что никакой многозадачности не может быть впринципе?
>


Нет, после раздвоения каждый процесс живет своей жизнью, только они находятся в одной группе и дочерний процесс, завершив свою работу, будет болтаться в памяти, став "зомби" (не потребляя при этом ресурсов процессора) до тех пор, пока родительский процесс не сделает wait либо не завершит свою работу.


"Вызов fork и процессы"
Отправлено dmi , 29-Мрт-04 19:19 
Вот утрированный кусок из моего кода, если можно, скажите где ошибка - Вы спасете огромное кол-во моих нервных клеток и благада моя не будет знать границ :-). Заранее спасибо.

while (1)
    {

        int msg_sock=0;
        int cli_len=sizeof(cli_addr);
        msg_sock=accept(m_sock, (struct sockaddr*)&cli_addr, (socklen_t*)&cli_len);
        if (msg_sock<=0)
            ...

        pid_t pid;
        if ((pid=fork ())==0)
        {
                OnConnect connect;
                connect.Begin();
                close (msg_sock);
                _exit(0);
        } else
        {
            /*Kill zombie */
            while (waitpid(pid, NULL, WNOHANG) > 0);
            /*если тут сделать wait() то одновременно смогут работать только 1 юзер*/
        }
    }
    close (m_sock);


"Вызов fork и процессы"
Отправлено vnp , 29-Мрт-04 21:03 
>Вот утрированный кусок из моего кода, если можно, скажите где ошибка -
>Вы спасете огромное кол-во моих нервных клеток и благада моя не
>будет знать границ :-). Заранее спасибо.
>
>while (1)
>    {
>        pid_t pid;
>        if ((pid=fork ())==0)
>        {
>    OnConnect connect;
>    connect.Begin();
>    close (msg_sock);
>    _exit(0);
>        } else
>        {
>            
>/*Kill zombie */
>            while (waitpid(pid, NULL, WNOHANG) > 0);
>            
>/*если тут сделать wait() то одновременно смогут работать только 1 юзер*/

В такой редакции, да, только один. Выше в треде были описаны две техники
(ловля SIGCHLD и double fork), позволяющие обойти проблему.


"Вызов fork и процессы"
Отправлено dmi , 30-Мрт-04 10:46 
Если я правильно понял - то надо сделать было так, только зомбики всеравно растут :-(
while (1)
    {
        int msg_sock=0;
        int cli_len=sizeof(cli_addr);
        msg_sock=accept(m_sock, (struct sockaddr*)&cli_addr, (socklen_t*)&cli_len);
        if (msg_sock<=0)
            ...

        pid_t pid;
        if((pid = fork()) > 0)
        {
            waitpid(pid, NULL, WNOHANG);
        } else
        {
            if(fork() > 0)
            {
                exit(0);
            } else
            {
                OnConnect connect;
                close (msg_sock);
            }
        }
}