Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по 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в чем дело? Откуда эта информация? Ведь все дочерние процессы завершили свою работу?
>Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по 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, либо двойным форком.
>>Пишу биллинг (любимое заняти российский юниксоидов :). Программа переодически по 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 проблема решена. А что такое двойной форк? Можете объяснить?
>Спасибо за ответ! С помощью wait проблема решена. А что такое двойной
>форк? Можете объяснить?Идея в следующем: Родитель должен ждать завершения потомка. Если родитель завершился первым, заботы о потомке берет на себя init. Если потомки порождаются и заканчиваются непредсказуемо и независимо друг от друга, бывает полезна такая модель:
if((pid = fork()) > 0) {
waitpid(pid, ...);
} else {
if(fork() > 0) {
exit(0);
} else {
exec...
}
}В такой редакции "первый потомок" завершается немедленно, т.е. wait() не блокируется, и не надо заморачиваться с portability issues вокруг SIGCHLD.
>Идея в следующем: Родитель должен ждать завершения потомка. Если родитель завершился первым,
>заботы о потомке берет на себя init. Если потомки порождаются и
>заканчиваются непредсказуемо и независимо друг от друга, бывает полезна такая модель:
>
>
>if((pid = fork()) > 0) {
> waitpid(pid, ...);
>} else {
> if(fork() > 0) {
> exit(0);
> } else {
> exec...
> }
>}
>
>В такой редакции "первый потомок" завершается немедленно, т.е. wait() не блокируется, и
>не надо заморачиваться с portability issues вокруг SIGCHLD.
Спасибо, идею понял.
Если следовать теории что после каждого раздвоения процесса надо ждать завершения процесса-потомка, то значит ли это что никакой многозадачности не может быть впринципе?
>Если следовать теории что после каждого раздвоения процесса надо ждать завершения процесса-потомка,
>то значит ли это что никакой многозадачности не может быть впринципе?
>
Нет, после раздвоения каждый процесс живет своей жизнью, только они находятся в одной группе и дочерний процесс, завершив свою работу, будет болтаться в памяти, став "зомби" (не потребляя при этом ресурсов процессора) до тех пор, пока родительский процесс не сделает wait либо не завершит свою работу.
Вот утрированный кусок из моего кода, если можно, скажите где ошибка - Вы спасете огромное кол-во моих нервных клеток и благада моя не будет знать границ :-). Заранее спасибо.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);
>Вот утрированный кусок из моего кода, если можно, скажите где ошибка -
>Вы спасете огромное кол-во моих нервных клеток и благада моя не
>будет знать границ :-). Заранее спасибо.
>
>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), позволяющие обойти проблему.
Если я правильно понял - то надо сделать было так, только зомбики всеравно растут :-(
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);
}
}
}