linux多进程并发服务器的accept返回-1

while (...) {
    int clnt_fd = accept(...);
    if (-1 == clnt_fd) {
        continue;
    }
    pid_t pid = fork();
    if (-1 == pid)...;
    else if (0 == pid) {
        close(serv_fd); 
        while(1) {
        	int len = read();
        	if (0 == len) break;
        	write();
        }
        close(clnt_fd)
        return;
    }
    else {close(clnt_fd)}
}
close(serv_fd)

这个if (-1 == clnt_fd) continue;的原因在于:
子进程结束的时候父进程收到SIGCHLD信号,此时如果父进程在accect处阻塞,由于accept不是可重入函数,因此父进程在响应信号中断accept会返回-1.
若不对-1加以判断,父进程将继续fork并且创建错误的子进程,若新的子进程也没有阻塞而是0=read()后退出,那么上述过程将陷入循环,导致程序执行出现问题.

上述过程使用wait()或者sigprocmask()都是不妥的
1.wait()阻塞主线程,使并发失去意义.
2.子进程退出时,应该注册SIGCHLD处理函数,以防止子进程成为僵尸进程.屏蔽掉SIGCHLD会产生僵尸进程

void handler(int) {
    int status;
    pid_t id = waitpid(-1, &status, WNOHANG);
    if(WIFEXITED(status)) {...}
}
struct sigaction act;
act.sa_flag=0;
sigemptymask(&act.sa_mask);
act.sa_handler=handle;

关于fork

int main() {
    int a{0};
    printf("a: %d\na is %d ", a++, a++);
    fork();
    fork();
    a = getpid();
    printf("pid: %d, a: %d, &a: %p\n", getpid(), a, &a);
    while(1) {}
    return 0;
}

输出结果:
a: 1
a is 0 pid: 19201, a: 19201, &a: 0x7ffd8994b3a4
a is 0 pid: 19202, a: 19202, &a: 0x7ffd8994b3a4
a is 0 pid: 19204, a: 19204, &a: 0x7ffd8994b3a4
a is 0 pid: 19203, a: 19203, &a: 0x7ffd8994b3a4

原因:
1.printf要注意缓冲区,fork前主进程通过’\n’清理了部分缓冲区,但是留下了部分缓冲区,缓冲区内容就是a is 0,所以fork()时这部分被复制到了子进程的空间,随下一次请缓冲区被打印.
2.函数参数由右向左执行,所以留下的缓冲区是a++一次的,打印出来的是a++两次的
3.子进程内,a的值不同,但是&a的值即a地址相同,这是因为&a表示虚拟内存的地址,不同进程的a真正对应的物理内存地址是不同的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值