看unix網(wǎng)絡(luò)編程第一卷的時(shí)候,碰到書(shū)上這樣一個(gè)例子: 一個(gè)并發(fā)服務(wù)器, 每一個(gè)客戶端連接服務(wù)器就fork一個(gè)子進(jìn)程.書(shū)上講到當(dāng)同時(shí)有n多個(gè)客戶端斷開(kāi)連接時(shí), 服務(wù)器端同時(shí)有n多個(gè)子進(jìn)程終止, 這時(shí)候內(nèi)核同時(shí)向父進(jìn)程發(fā)送n多個(gè)sigchld信號(hào).它的sigchld信號(hào)處理 函數(shù)如下: void sig_chld(int signo) { pid_t pid; int stat; while((pid = waitpid(-1, &stat, WNOHANG)) > 0){ printf("child %d terminated\n", pid); } return; }
我的問(wèn)題是:既然sigchld是不可靠的信號(hào),進(jìn)程就不可能對(duì)sigchld進(jìn)行排隊(duì), 直接丟棄了sigchld信號(hào)(當(dāng)進(jìn)程注冊(cè)信號(hào)的時(shí)候,發(fā)現(xiàn)已有sigchld注冊(cè)進(jìn)未決信號(hào), 因?yàn)閮?nèi)核同時(shí)發(fā)送多個(gè)sigchld).請(qǐng)問(wèn)大家上面的代碼是如何保證不產(chǎn)生僵尸進(jìn)程的.謝謝!
xltao 回復(fù)于:2006-09-15 15:28:58
高人指點(diǎn)啊
linternt 回復(fù)于:2006-09-15 16:03:58
用消息隊(duì)列吧,子進(jìn)程退出前把自已的PID寫(xiě)進(jìn)隊(duì)列 然后父進(jìn)程去讀,不過(guò)pid = waitpid(-1, &stat, 0); 讓父進(jìn)程阻塞在調(diào)用這塊,不過(guò)如果你想讓waitpid快帶返回也行, 如果沒(méi)接到子進(jìn)程退出信號(hào),你可以把這個(gè)PID再寫(xiě)進(jìn)去,然后繼續(xù)讀,直到接到SIGCHLD為止。
以前在項(xiàng)目中遇到過(guò)此問(wèn)題,大量的并發(fā)進(jìn)程往往造成很多的僵死進(jìn)程,以至于程序無(wú)法響應(yīng),當(dāng)時(shí)被這個(gè)問(wèn)題弄得很頭痛,直到想到這個(gè)方法以后才有效的解決了上述問(wèn)題。
為方法就等于實(shí)現(xiàn)了一個(gè)對(duì)SIGCHLD的排隊(duì)機(jī)制。我一直在大型的項(xiàng)目中用這個(gè),很不錯(cuò)。
思一克 回復(fù)于:2006-09-15 16:08:45
你能給出一簡(jiǎn)短的例子引起你說(shuō)的那個(gè)問(wèn)題的程序?
susesuse 回復(fù)于:2006-09-15 16:36:42
我的看法,不一定對(duì)啊,呵呵.先看看下面的程序.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void sig_child(int signo)
{ pid_t pid;
int stat;
while( (pid = waitpid(-1,&stat,WNOHANG)) > 0)
{
printf("child %d exit\n",pid);
sleep(5);//這應(yīng)該導(dǎo)致信號(hào)丟失吧?
}
return;
}
void child_func()
{
return;
}
int main()
{
pid_t pid;
int i = 0;
signal(SIGCHLD,sig_child);
for(;i < 5;i ++)
{
if( (pid = fork()) == 0)
{
child_func();
printf("child function finished\n");
exit(0);
}
else if(pid > 0)
{
continue;
}
else
{
printf("fork failed\n");
exit(1);
}
}
return 0;
}
linux:~/test # gcc -o waitpid waitpid.c linux:~/test # ./waitpid child function finished child 7449 exit child function finished child 7450 exit child function finished child 7454 exit child function finished child 7455 exit child function finished child 7459 exit
對(duì)于SIGCHILD信號(hào)(屬于不可靠信號(hào),不支持信號(hào)排隊(duì).),按理說(shuō)應(yīng)該有信號(hào)丟失,可為什么還是輸出5次呢?這實(shí)際上沒(méi)有把握清楚waitpid(-1,&stat,WNOHANG)函數(shù)的作用.它是用來(lái)用來(lái)檢測(cè)進(jìn)程是否已結(jié)束并回收僵尸進(jìn)程的,在這個(gè)程序里信號(hào)確實(shí)會(huì)丟失的.但waitpid函數(shù)不是由SIGCHILD信號(hào)驅(qū)動(dòng)的. |