web服务器程序中要特别注意问题:
一、创建子进程后不能用while(1),注意与一般的socket程序不同。
二、避免产生僵尸进程
三、read函数的阻塞问题
最简单的并发服务器,莫过于当accept返回时,fork一个进程去处理客户端的连接。
典型server框架是:
listenFd=socket();
bind(listenFd...);
listen(listenFd...);
while(1)
{
connectFd=accept(listenFd...);
if(0 == fork())
{
close(listenFd);//子进程
do_something(connectFd);
close(connectFd);
exit(0);
}
close(connectFd);//父进程
}
fork说明:
子进程可以通过getpipd获取父进程的pid,父进程无法通过系统调用实时获取子进程的pid,为了管理子进程,只能在fork执行返回时将子进程的进程号记录下来;fork执行后,原进程所持有的文件描述符会被复制,即文件表项引用计数会增加,父子进程执行close时,会减少引用计数。
zombie的出现是由于parent没有尽到职责,未wait子进程.
有四个办法 (不只四个):
1. 使用thread
2. 子进程在结束前发送信号,父进程在信号处理中wait
3. 父进程在创建子进程后,马上创建一个自己的接班人,然后
自杀. 例如:
while(1)
{
recvfromclient(s);
if(fork()==0)
{
idledata(s);
exit(0);
}
if(fork()!=0)
{
exit(0);
}
}
4. 父进程在创建子进程后,子进程再创建孙子进程,由孙子进程
完成任务. 而父进程等待(不成大器的)子进程完成. 例如:
while(1)
{
int pid;
recvfromclient(s);
if((pid = fork())==0)
{
if (fork() == 0)
{
idledata(s);
exit(0);
}
exit(0);
}
waidpid(pid, NULL);
}
运行后终端没有输出,停止后会输出,通过在main中添加setbuf(stdout,NULL)解决问题,原来是因为默认输出流存在buffer机制,通过上面语句, 取消buffer