http://blog.csdn.net/AAA20090987/article/month/2013/01
http://blog.csdn.net/AAA20090987/article/category/1208167
//处理SIGCHLD信号,防止子进程变成僵死进程
Signal(SIGCHLD, sig_child);
http://blog.sina.com.cn/s/blog_ac9fdc0b0101jtgx.html
多进程服务器中accept函数可重入问题
while(1) { clilen = sizeof(cliaddr); //接受一个来自客户端的连接 //如果没有连接请求,就使程序睡眠,直到有连接请求--这是accept函数的特性 //accept函数返回一个描述符,这个socket(connfd)用于同连接到的客户的通信 connfd = accept(listenfd, (SA*)&cliaddr, &clilen); if( connfd < 0 ) { //accetp()是慢系统调用,在信号产生时会中断其调用, //并将errno变量设置为EINTR,此时应重新调用 if( errno == EINTR ) continue; else error_quit("accept error"); } //产生一个子进程,让它处理与(某个客户端的)通信 childpid = Fork(); if( childpid == 0 ) { Close(listenfd); str_echo(connfd); return 0; } //输出客户端的IP地址与端口号,还有处理(子)进程的PID printf("connection from %s, port %d. process with clild %d\n", Inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port), childpid); //与客户端的通信由子进程来处理,所以关闭此套接字 Close(connfd); }
先accept,再fork,子进程中可以直接访问connfd
多线程模型下:
pthread_detach(), PTHREAD_CREATE_DETACH “脱离线程” 在退出时将自行释放其占用的系统资源。
进程池模型:prefork
//如果没有可用的子进程,就晳时关闭套接字(不accept)
//将请求阻塞在内核中
if (navail <= 0)
FD_CLR(listenfd, &rset);
nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL);
//打开管道两次,一次只读,一次只写
readfifo = Open(SERV_FIFO, O_RDONLY, 0);
//这个描述符从来不用,但如果我们总是有一个该FIFO的描述符打开着用于写,
//那么客户端都关闭时,服务器的read只会被阻塞,而不会返回0
dummyfd = Open(SERV_FIFO, O_WRONLY, 0);