C/C++网络编程8——多进程服务器端之销毁僵尸进程
上一节提到,当子进程执行结束,父进程还在执行,在父进程结束之前子进程会成为僵尸进程,那么怎么销毁僵尸进程呢?父进程主动接收子进程的返回值。
销毁僵尸进程的方法:
1:使用wait函数
2:使用waitpid函数
3:利用信号
1:使用wait函数销毁僵尸进程
#include <sys/wait.h> pid_t wait(int *status);
// 成功返回终止的子进程id,失败返回-1
在父进程中调用wait函数以后,如果有子进程已经执行结束,那么子进程传回的返回值将存储到status所指的内存中,但是如果没有子进程执行结束,父进程将会阻塞在wait函数,直到有子进程执行结束,这是一种不好的实现方法。
// wait函数销毁僵尸进程
#include <iostream>
#include <unistd.h>
#include <sys/wait.h> using namespace std; int main()
{
pid_t pid = fork();
if (pid < ) {
cout << "fork() failed" << endl;
return ;
} if (pid == ) {
return ;
} else {
int status = ;
wait(&status);
if (WIFEXITED(status)) { // 子进程正常结束
cout << "child return: " << WEXITSTATUS(status) << endl;
} sleep();
} return ;
}
2:使用waitpid函数销毁僵尸进程
wait函数会使程序阻塞,可换用waitpid函数杀死僵尸进程,同时能避免程序阻塞。
#include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options);
// 成功返回终止的子进程id,失败返回-1
// pid : 等待终止的子进程id,传-1代码任意子进程终止
// status:和wait函数的参数一样
// options:传递WNOHANG,没有终止的子进程也不进入阻塞状态,返回0
#include <iostream>
#include <unistd.h>
#include <sys/wait.h> using namespace std; int main()
{
pid_t pid = fork();
if (pid < ) {
cout << "fork() failed" << endl;
return ;
} if (pid == ) {
sleep();
return ;
} else {
int status = ;
while (!waitpid(pid, &status, WNOHANG)) {
sleep();
cout << "child proc is not finish" << endl;
} if (WIFEXITED(status)) { // 子进程正常结束
cout << "child return: " << WEXITSTATUS(status) << endl;
}
} return ;
}
3:利用信号销毁僵尸进程
利用wait函数能销毁僵尸进程,但是会阻塞父进程;利用waitpid也能销毁僵尸进程并且不阻塞父进程,但是也需要不停的去检查子进程结束没有。所以wait及waitpid方式都不完美。于是引入了信号,信号是在特定事件发生时由操作系统向进程发送的消息,接收到消息的进程做信号处理。信号的使用方法是先注册信号,告诉操作系统,当某个信号发生时,要做什么事情。
signal(SIGCHLD, do_what); SIGCHLD是子进程结束的信号,当子进程结束时,执行do_what函数。
其他常用信号,SIGALRM:已到通过调用alarm函数注册的时间;SIGINT:输入CTRL+C
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h> using namespace std; void read_child_proc(int sig)
{
int status;
pid_t pid = waitpid(-, &status, WNOHANG); if (WIFEXITED(status)) { // 子进程正常结束
cout << "child proc finish: " << pid <<" " << WEXITSTATUS(status) << endl;
}
} int main()
{
pid_t pid = fork();
if (pid < ) {
cout << "fork() failed" << endl;
return ;
} signal(SIGCHLD, read_child_proc); // 注册子进程结束信号,当子进程结束时调用read_child_proc函数 if (pid == ) {
return ;
} else {
sleep();
cout << "master proc wake up" << endl;
} return ;
}
执行程序发现 master proc wake up并不是等30秒以后才输出,而输出很快,说明当注册子进程结束信号以后,当有子进程执行结束时,会马上唤醒sleep的进程。
C/C++网络编程8——多进程服务器端之销毁僵尸进程的更多相关文章
- C/C++网络编程7——多进程服务器端之fork函数
通过前面几节的内容,我们已经可以实现基本的C/S结构的程序了,但是当多个客户端同时向服务器端请求服务时,服务器端只能按顺序一个一个的服务,这种情况下,客户端的用户是无法忍受的.所以虚实现并发的服务器端 ...
- Linux 网络编程详解七(并发僵尸进程处理)
在上一篇程序框架中,解决了子进程退出,父进程继续存在的功能,但是多条客户端连接如果同一时间并行退出,导致服务器端多个子进程同一时间全部退出,而SIGCHLD是不可靠信号,同时来多条信号可能无法处理,导 ...
- C/C++网络编程9——多进程服务器端实现
#include <iostream> #include <unistd.h> #include <cstdlib> #include <arpa/inet. ...
- TCP/IP网络编程之多进程服务端(二)
信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非阻塞等待子进程销毁的函数,但有一个不好的缺 ...
- TCP/IP网络编程之多进程服务端(一)
进程概念及应用 我们知道,监听套接字会有一个等待队列,里面存放着不同客户端的连接请求,如果有一百个客户端,每个客户端的请求处理是0.5s,第一个客户端当然不会不满,但第一百个客户端就会有相当大的意见了 ...
- 网络编程并发 多进程 进程池,互斥锁,信号量,IO模型
进程:程序正在执行的过程,就是一个正在执行的任务,而负责执行任务的就是cpu 操作系统:操作系统就是一个协调.管理和控制计算机硬件资源和软件资源的控制程序. 操作系统的作用: 1:隐藏丑陋复杂的硬件接 ...
- python并发编程之多进程1-----------互斥锁与进程间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python并发编程之多进程1--(互斥锁与进程间的通信)
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python并发编程之多进程1互斥锁与进程间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
随机推荐
- 左偏树 (bzoj 2809)
Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...
- touch命令修改时间
实例[rhel7]: [root@localhost test]# stat 1.txt 文件:"1.txt" 大小:0 块:0 IO 块:4096 普通空文件设备:fd00h/6 ...
- 计算机二级-C语言-程序填空题-190107记录
//给定程序的功能是:调用fun函数建立班级通讯录.通讯中记录每位学生的编号,姓名和电话号码.班级的人数和学生的信息从键盘读入,每个人的信息作为一个数据块(代表要使用结构体)写到名为myfile5.d ...
- vue中watch和computed为什么能监听到数据的改变以及不同之处
先来个流程图,水平有限,凑活看吧-_-|| 首先在创建一个Vue应用时: var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } ...
- php-cp(php连接池)扩展的安装
今天看到php有连接池的扩展,不管效果怎么样,都值得一试,这样才会有突破. 先从guthub上搜索源码:[ https://github.com/swoole/php-cp ] 通过命令clone到自 ...
- Linux-VMware 15 虚拟机黑屏问题
VMware 15 虚拟机黑屏问题 最近终于舍弃win7,换了win10的操作系统... VM12不兼容,各种问题频出,于是换了VM15. 新装了kali2019.03,结果刚装好不久,在某一 ...
- python 读取一个文件夹下的所jpg文件保存到txt中
最近需要使用统计一个目录下的所有文件,使用python比较方便,就整理了一下代码. import os def gci(filepath): files = os.listdir(filepath) ...
- mysql设置定时任务(对于中控心跳包的实现有意义)
转载:https://www.cnblogs.com/laowu-blog/p/5073665.html 目前用途:因为 脚本正常开关会给中控发送消息 但是万一脚本被强制关闭 没有触发脚本关闭事件就无 ...
- 在ubuntu永久添加alias
1. cd 进入家目录 操作如下: cd ~ 2.显示隐藏文件 操作如下:ls -al 3.vim打开.bashrc 操作如下: vim .bashrc 4.按a编辑添加alias example=' ...
- 将.NET Core Web Api发布到Linux(CentOS 7 64)
将.NET Core(2.1) Web Api发布到Linux(CentOS 7 64) 近来在学习linux相关的一些东西,然后正巧想试一下把core的应用程序发布到Linux,毕竟跨平台.尝试一下 ...