多进程网络模型

代码框架
server.c :
int main()
{
     申请 listensocket
     while(1)
     {
          if((connnectfd = accept(...))==0)
          {
               if((childpid == fork())==0)
               {
                   close(listenfd);
                   负责通信逻辑
               }
               else
               {
                   close(connectfd);
               }
          }
          else
          {
              异常处理
          }
    }
    return 0;
}    
关于close

  因为子进程会基本上把父进程pcb复制一份,所以所有的标准输入、输出、错误,还有虚拟地址空间和文件描述符表都会复制一份,所以这个时候对应的相文件描述符的引用计数会加1。
  这也就意味着如果父进程在fork完不调用close的话,connectfd 会一直存在于文件描述符表,首先它会浪费资源,其次最重要的是服务器端这边逻辑虽然已经处理完,但是并没有真正调用close,这就造成可能对端client已经发了Fin段进入了 FIN_WAIT2状态,但是服务器端一直没有却发FIN端(虽然child 读到了EOF也确实调用了close但是奈何引用计数是2并不能触发连接终止),这就造成了空置的链接会浪费服务器资源。

关于信号处理

  首先一个服务器是不能一直阻塞于waitpid 或者 轮询非阻塞于waitpid ,这样都不合适。因为server还需要去接受每一个到来的连接,一直忙于waitpid不太合适。但是不处理僵尸进程又不太合适,所以我们通过SIGCHID异步去处理。

void sig_child(int signo)
{
     pid_t pid;
     int stat;
     pid = wait(&stat);
     if(pid > 0 &&  (stat & 0x7f)==0)
     {
          printf("pid %d 's exit code : %d", stat>>8 & 0xff);
     }
     else if(pid >0 )
     {
          printf("pid %d sigcode:%d",stat&0x7f);
     }
     else 
     {
        perror("In Sigchild 's wait");
     }
     return ;// 这个return 只是为了代表这个函数还是会返回到被中断处
 }
wait status变量

status

EINTR

  低速的系统调用被信号会重启,也就是说如果终端I/O或者网络I/O的系统调用被中断了,那么kernel自动重启。但是也并不是所有unix系统都会重启,posix并没有规定必须重启,所以为了移植性,我们可以在用sigaction注册时候的时候,通过 struct sigaction 中的 sa_flags成员变量来设置。

ifdef SA_RESTART 
         act.sa_flags |= SA_RESTART;
endif

  当然也可以通过检查返回值EINTR来重启,大多数Linux的系统调用函数,一般面对EINTR时都应该重启这个系统调用(read/write/open/accept…),因为这个系统调用是被信号中断的,它不是一种错误。所以为了可移植性我们不能够依靠 kernel帮我们默认重启系统调用,我们得自己搞定,所以就好好判断EINTR吧。
  其次继续看上面的框架,如果没有正确处理信号中断,kernel也没有自动重启。那么当注册完handler函数后,发送异步中断,这个时候系统调用可能会被中断,那么我们没有正确处理EINTR的话,可能代码逻辑把这个错误当成 Error 或者 Fatal 来处理直接终止程序,那么就坑了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值