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