阻塞I/O和进程模型

父进程和子进程

fork 函数实现的时候,实际上会把当前父进程的所有相关值都克隆一份,包括地址空间、打开的文件描述符、程序计数器等,就连执行代码也会拷贝一份,新派生的进程的表现行为和父进程近乎一样,就好像是派生进程调用过 fork 函数一样。为了区别两个不同的进程,实现者可以通过改变 fork 函数的栈空间值来判断,对应到程序中就是返回值的不同。

if (fork() == 0) {
	do_child_process();//子进程执行代码
} else {
	do_parent_process();//父进程执行代码
}

当一个子进程退出时,如果不回收,就会变成僵尸进程。占用不必要的内存空间和系统资源
有两种方式可以在子进程退出后回收资源

pid_t wait(int *statloc);
pid_t waitpid(pid_t, int *statloc, int options);
  • 函数返回值,表示已终止子进程的进程 ID 号,
  • statloc指针返回子进程终止的实际状态,这个状态可能的值为正常终止、被信号杀死、作业控制停止等。

如果没有已终止的子进程,而是有一个或多个子进程在正常运行,那么 wait 将阻塞(pid值-1),直到第一个子进程终止。

处理子进程退出方式一般是注册一个信号处理函数,捕捉信号SIGCHILD信号,然后再在信号处理函数里调用waitpid函数来完成子进程资源的回收

signal(SIGCHLD, sigchld_handler);
阻塞 I/O 的进程模型

我们假设有两个客户端,服务器初始监听在套接字 lisnted_fd 上。当第一个客户端发起连接请求,连接建立后产生出连接套接字,此时,父进程派生出一个子进程,在子进程中,使用连接套接字和客户端通信,因此子进程不需要关心监听套接字,只需要关心连接套接字;父进程则相反,将客户服务交给子进程来处理,因此父进程不需要关心连接套接字,只需要关心监听套接字
在这里插入图片描述
假设父进程之后又接收了新的连接请求,从 accept 调用返回新的已连接套接字,父进程又派生出另一个子进程,这个子进程用第二个已连接套接字为客户端服务。
在这里插入图片描述
现在,服务器端的父进程继续监听在套接字上,等待新的客户连接到来;两个子进程分别使用两个不同的连接套接字为两个客户服务。

总结

使用阻塞I/O和进程模型,创建每一个独立的子进程来进行服务,是非常简单有效的实现方式,但可能很难满足高性能程序的需求。

  • 要注意对套接字的关闭梳理
  • 注意对子进程回收,避免产生僵尸进程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值