C语言网络编程server.c中SIGCHLD相关代码功能及作用疑问
问题1:sigaction配置代码的作用与服务端添加该逻辑的原因
这段代码的核心作用是为**SIGCHLD(子进程退出信号)**注册自定义信号处理函数,避免服务端产生僵尸进程。逐行逻辑解释如下:
sa.sa_handler = sigchld_handler;:指定SIGCHLD信号触发时的处理函数为自定义的sigchld_handlersigemptyset(&sa.sa_mask);:清空信号掩码,保证信号处理函数执行期间不会被其他信号意外打断sa.sa_flags = SA_RESTART;:设置信号触发如果打断了accept()、recv()这类阻塞的网络系统调用时,内核会自动重启该系统调用,而不是返回错误中断服务端正常逻辑- 最后调用
sigaction()完成信号注册,如果注册失败直接退出进程,避免后续运行产生不可预期的问题
服务端必须添加该逻辑的原因:
Beej指南里的并发流套接字服务端采用的是fork()子进程处理单连接的架构:主进程负责监听端口,accept()拿到新连接后就创建子进程处理该连接的所有请求,子进程处理完请求后就会退出。子进程退出时内核会向父进程(服务端主进程)发送SIGCHLD信号,如果父进程不处理该信号,退出的子进程会变成僵尸进程,持续占用系统进程表资源,长期运行会耗尽系统进程ID,导致服务端无法再创建新的子进程处理用户请求。
问题2:sigchld_handler函数的功能与触发时机
触发时机
每当服务端fork出来的子进程退出时,内核会主动向服务端主进程发送SIGCHLD信号,此时内核会自动调用提前注册好的sigchld_handler函数。
核心功能
该函数的作用是回收所有已经退出的子进程的内核资源,彻底消灭僵尸进程。标准实现逻辑如下:
void sigchld_handler(int s) { // 保存原有errno值,避免信号处理意外修改系统调用的错误返回值 int saved_errno = errno; // 循环回收所有已退出的子进程,WNOHANG表示没有待回收子进程时立刻返回不阻塞 while(waitpid(-1, NULL, WNOHANG) > 0); errno = saved_errno; }
这里用循环加WNOHANG参数的原因是:如果多个子进程同时退出,内核大概率只会发送一次SIGCHLD信号,循环可以一次性回收所有已经退出的子进程,不会出现资源泄漏。
内容的提问来源于stack exchange,提问作者coder_sam97
相关产品推荐
相关产品推荐

