news 2026/5/1 9:44:49

Linux多进程服务器编程:信号回收与资源管理详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux多进程服务器编程:信号回收与资源管理详解

一、引言

在上一篇文章中,我们实现了基本的多进程TCP服务器。但那个版本存在一个严重问题:子进程退出后没有被回收,会产生僵尸进程。本文将深入讲解如何使用信号机制优雅地回收子进程资源,并完善多进程服务器的实现。

二、多进程服务器的资源管理问题

2.1 进程复制机制回顾

当使用fork()创建子进程时,会发生以下复制:

pid_tpid=fork();

复制内容:

  • 用户区:堆区、栈区、全局数据区、代码区
  • 内核区:文件描述符表
  • 不复制:进程ID、父进程ID、进程状态

关键特性:

  • 父子进程拥有独立的地址空间
  • 父进程修改数据不影响子进程
  • 文件描述符被复制但指向相同的内核对象

2.2 僵尸进程问题

问题描述:

// 子进程退出exit(0);// 子进程变成僵尸进程(Z状态)

子进程退出后,如果父进程不回收,会导致:

  • 进程表项被占用
  • 系统资源泄漏
  • 大量僵尸进程可能耗尽进程表

查看僵尸进程:

psaux|grepZ# 或ps-ef|grepdefunct

2.3 回收时机冲突

父进程需要同时处理两件事:

while(1){intcfd=accept(lfd,...);// 阻塞等待新连接wait(NULL);// 阻塞等待子进程退出}

问题:accept()wait()都是阻塞函数,无法同时执行!

解决方案:使用信号机制异步回收子进程

三、信号机制回收子进程

3.1 SIGCHLD信号原理

当子进程状态改变(退出、停止、继续)时,内核会向父进程发送SIGCHLD信号(信号编号17)。

工作流程:

子进程退出 → 内核发送SIGCHLD → 父进程捕获信号 → 执行回调函数 → 回收子进程

3.2 sigaction函数详解

函数原型
#include<signal.h>intsigaction(intsignum,conststructsigaction*act,structsigaction*oldact);

参数说明:

  • signum:要捕获的信号编号(如SIGCHLD
  • act:新的信号处理方式
  • oldact:保存旧的信号处理方式(通常传NULL)
sigaction结构体
structsigaction{void(*sa_handler)(int);// 信号处理函数(简单版)void(*sa_sigaction)(int,siginfo_t*,void*);// 信号处理函数(详细版)sigset_tsa_mask;// 信号屏蔽字intsa_flags;// 标志位void(*sa_restorer)(void);// 已废弃};

关键成员:

  • sa_handler:简单的信号处理函数
  • sa_sigaction:带详细信息的处理函数(与sa_handler互斥)
  • sa_flags
    • 0:使用sa_handler
    • SA_SIGINFO:使用sa_sigaction
  • sa_mask:信号处理期间要屏蔽的信号集

3.3 信号处理函数实现

#include<signal.h>#include<sys/wait.h>// 信号处理回调函数voidsigchld_handler(intsignum){printf("捕获到信号: %d (SIGCHLD)\n",signum);// 循环回收所有退出的子进程pid_tpid;while((pid=waitpid(-1,NULL,WNOHANG))>0){printf("成功回收子进程,PID = %d\n",pid);}}

关键点:

  • 使用while循环:因为信号不支持排队,多个子进程同时退出只会收到一次信号
  • waitpid(-1, NULL, WNOHANG)
    • -1:等待任意子进程
    • WNOHANG:非阻塞模式,没有子进程退出时立即返回0

3.4 注册信号处理

voidregister_signal_handler(){structsigactionact;// 1. 设置信号处理函数act.sa_handler=sigchld_handler;// 2. 设置标志位(使用sa_handler)act.sa_flags=0;// 3. 清空信号屏蔽字(不屏蔽任何信号)sigemptyset(&act.sa_mask);// 4. 注册信号处理if(sigaction(SIGCHLD,&act,NULL)==-1){perror("sigaction error");exit(1);}printf("SIGCHLD信号处理已注册\n");}

四、完整代码实现

4.1 改进的服务器端代码

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<signal.h>#include<sys/wait.h>#definePORT9999#defineBUFFER_SIZE1024#defineMAX_LISTEN128// 信号处理函数:回收子进程voidsigchld_handler(intsignum){printf("\n[信号] 捕获到SIGCHLD信号 (编号: %d)\n",signum);pid_tpid;intcount=0;// 循环回收所有退出的子进程while((pid=waitpid(-1,NULL,WNOHANG))>0){count++;printf("[回收] 成功回收子进程,PID = %d\n",pid);}if(count>0){printf("[回收] 本次共回收 %d 个子进程\n",count);}}// 注册信号处理voidregister_signal_handler()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 5:24:22

3个维度突破百度网盘限速:给技术人的解析工具全指南

3个维度突破百度网盘限速&#xff1a;给技术人的解析工具全指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 百度网盘作为国内主流的云存储服务&#xff0c;其限速问题一直…

作者头像 李华
网站建设 2026/5/1 4:43:34

亲测CAM++语音比对效果,科哥镜像真实体验分享

亲测CAM语音比对效果&#xff0c;科哥镜像真实体验分享 最近在做声纹验证相关的项目&#xff0c;需要一个开箱即用、中文支持好、部署简单的说话人识别工具。试过好几个方案后&#xff0c;偶然发现科哥发布的这个CAM镜像——界面清爽、操作直观、响应迅速&#xff0c;最关键的…

作者头像 李华
网站建设 2026/4/30 13:37:14

探索XUnity Auto Translator:破解游戏本地化难题的技术密码

探索XUnity Auto Translator&#xff1a;破解游戏本地化难题的技术密码 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 在全球化游戏市场竞争日益激烈的今天&#xff0c;游戏本地化技术已成为连接开发者与…

作者头像 李华
网站建设 2026/4/23 16:17:02

7个秘诀让你成为视频资源管理大师:哔哩下载姬完全指南

7个秘诀让你成为视频资源管理大师&#xff1a;哔哩下载姬完全指南 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#…

作者头像 李华
网站建设 2026/5/1 6:10:31

为什么IQuest-Coder-V1部署总卡顿?显存优化实战指南

为什么IQuest-Coder-V1部署总卡顿&#xff1f;显存优化实战指南 你是不是也遇到过这样的情况&#xff1a;下载了IQuest-Coder-V1-40B-Instruct镜像&#xff0c;满怀期待地启动服务&#xff0c;结果模型加载到一半就卡住&#xff0c;GPU显存占用飙到98%&#xff0c;nvidia-smi里…

作者头像 李华
网站建设 2026/3/28 5:15:46

Qwen3-14B部署耗时长?预加载优化提速50%实战案例

Qwen3-14B部署耗时长&#xff1f;预加载优化提速50%实战案例 1. 为什么Qwen3-14B值得你花时间优化&#xff1f; 你有没有试过在本地跑Qwen3-14B&#xff0c;点下启动命令后盯着终端等了快两分钟&#xff0c;才看到第一行日志&#xff1f;不是模型推理慢&#xff0c;是它卡在“…

作者头像 李华