gpt4 book ai didi

c - unix网络编程书中的wait函数?

转载 作者:太空宇宙 更新时间:2023-11-04 04:43:18 25 4
gpt4 key购买 nike

书中第5章Unix Network Programming Stevens et al 有一个服务端程序和一个客户端程序如下:

服务器

mysignal(SIGCHLD, sig_child);
for(;;)
{
connfd = accept(listenfd, (struct sockaddr *)&ca, &ca_len);

pid = fork();
if(pid == 0)
{
//sleep(60);
close(listenfd);
str_echo(connfd);
close(connfd);
exit(0);
}
close(connfd);
}

函数 sig_child 用于处理信号 SIGCHLD;代码如下:

void sig_child(int signo)
{
pid_t pid;
int stat;
static i = 1;
i++;
while(1)
{
pid = wait(&stat);
if(pid > 0)
{
printf("ith: %d, child %d terminated\n", i, pid);
}
else
{
break;
}
}
//pid = wait(&stat);
return;
}

客户端

for(i = 0 ; i < 5; i++)
{
sockfd[i] = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd[i] < 0)
{
perror("create error");
exit(-1);
}

memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(5900);

if(inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1)
{
perror("inet_pton error");
exit(-1);
}
connect(sockfd[i], (struct sockaddr *)&sa, sizeof(sa));
}
str_cli(sockfd[0], stdin);
exit(0);

在客户端的源码中可以看到,程序会与服务器端建立5个连接,但程序中只使用了1个连接; str_cli 完成后,调用 exit(0)。并且应该关闭所有连接,然后服务器中的五个子进程将退出,并将 SIGCHLD 发送给父进程,父进程使用函数 sig_child 来处理 SIGCHLD。然后 while 循环将确认所有子进程都将被父进程正确等待。我对程序进行了几次测试;效果很好,所有的 child 都会被打扫干净。

但是在书中,作者写道“wait 无法正常工作,因为函数 wait 可能在所有子进程退出之前被阻塞”。那么书上的说法对吗?如果是对的,请您详细解释一下。 (PS:我认为 while 语句中的 wait 会正确处理所有子进程的退出。)

最佳答案

问题不在于 wait,而在于信号传递。书中的sig_chld函数没有while循环,它只等待一个 child

void sig_child(int signo)
{
pid_t pid;
int stat;
pid = wait(&stat);
printf("child %d terminated\n", pid);
return;
}

当客户端退出时,所有连接都关闭,所有子连接最终终止。现在,第一个 SIGCHLD 信号被传递,并且在进入信号处理程序时,信号被阻塞。任何进一步的信号都不会排队,因此会丢失,从而导致服务器中的僵尸 child 。

您可以通过将 wait 包装在某个循环中来解决此问题,就像您所做的那样。另一种解决方案是显式忽略 SIGCHLD,这在您不需要 child 的退出状态时有效。


虽然 wait 在一个循环中最终等待所有 child ,但它有一个缺点,即 wait 阻塞,如果还有 child 在运行。这意味着进程会卡在信号处理程序中,直到所有子进程都终止。

书上的解决方法是用waitpid在循环中使用选项 WNOHANG

while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);

这个循环等待所有终止的 child ,但会尽快退出,即使有正在运行的 child 也是如此。


要重现信号处理程序中挂起的服务器,您必须执行以下操作

  • 启动服务器
  • 开始第一个客户
  • 启动第二个客户端
  • 关闭其中一个客户
  • 开始第三个客户
  • 在第三个客户端输入文字
    你不会得到回应

关于c - unix网络编程书中的wait函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23802864/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com