在网络编程中,单线程服务器最致命的问题在于其“阻塞性”——当服务器正在与一个客户端通信时,其他所有连接请求都会被拒之门外。
为了实现真正的并发,我们需要引入多进程模型。本文将深入探讨如何利用 Linux 的进程创建机制,构建一个高性能的并发服务器。
一、 多进程并发的核心原理
1.fork()与资源继承
在 Linux 中,使用fork()创建子进程时,内核会为子进程拷贝父进程的虚拟地址空间。
- 用户区拷贝:包括代码区、全局数据区、堆和栈。这意味着子进程拥有和父进程完全一样的逻辑代码和数据副本。
- 内核区拷贝:其中最关键的是文件描述符表。
- 父进程在
accept()成功后得到一个通信文件描述符cfd。 - 调用
fork()后,子进程的文件描述符表也拥有这个cfd。 - 父子进程独立性:虽然共享同一个内核文件对象,但它们对数据的修改互不干扰。
- 父进程在
2. 职责分工:父进程监听,子进程通信
为了避免进程阻塞互相影响,我们采用以下架构:
- 父进程(唯一):专职负责
accept()。它像一个前台接待,不断循环等待新连接。 - 子进程(多个):一旦有新连接,父进程就派生出一个子进程。子进程专职负责
read/write(通信)。子进程的数量与当前连接的客户端数成 1:1 关系。
二、 解决方案实现
在实现多进程服务器时,有一个细节必须注意:关闭不需要的文件描述符。
- 子进程不需要监听,应关闭
lfd。 - 父进程不需要通信,应关闭
cfd。
1. 详细代码案例
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<arpa/inet.h>#include<signal.h>#include<sys/wait.h>// 信号处理函数:回收子进程资源,防止僵尸进程voidcallback(intnum){while(waitpid(-1,NULL,WNOHANG)>0