Linux系统【三】回收子进程

孤儿进程

父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,则称init进程领养孤儿进程。现在好像是用户进程中的system进程。

僵尸进程

进程终止,父进程不进行回收,自己成残留资源(PCB)存放在内核中,变成僵尸进程。

子进程死亡以后会将自己占用的内存(4G)释放,但是会将死亡信息放在自己的PCB中,希望父进程调用得到子进程的死亡信息以后再清除PCB。需要注意的是僵尸进程是不能使用kill命令清除掉的,因为kill命令知识用来终止进程的,而僵尸进程已经终止。这就要求我们手动回收子进程。

这里的僵尸进程特别指的是父进程没有结束而子进程已经结束,如果父进程结束就算我们不手动回收也会自动回收(实际过程是父进程结束以后没有回收的子进程变成孤儿进程被init进程或者system进程回收)

wait函数回收子进程

一个进程在终止时会关闭所有的文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或者waitpid获取这些信息,然后彻底清除这个进程。

shell下一个进程的退出状态可以用特殊变量$?查看,因为shell是他的父进程,当它终止时shell调用wait或者waitpid得到它的退出状态同时彻底清除掉这个进程。

wait函数可以回收子进程终止信息,该函数有三个功能:

  • 阻塞等待子进程退出:如果子进程没有结束父进程不会干其他的事情
  • 回收子进程残留的PCB资源
  • 获取子进程结束状态(退出原因)

一次wait函数只能清除一个子进程

pid_t wait(int *status); 

返回值:如果成功返回子进程ID,如果失败返回-1(没有子进程的话就会报错)

status保存结束状态

  • 进程正常结束
WIFEXITED(status) 为非0说明是正常退出
WEXITSTATUS(status)如果上面宏为真,使用这个宏获取进程退出状态(exit的参数)
  • 进程异常终止(收到信号终止,例如段错误、总线错误、浮点数例外错误)
WIFSIGNALED(status) 为非0,说明程序异常终止
WTERMSIG(status)如果上面宏为真使用此宏 取得使得进程终止的那个信号的编号
  • 进程处于暂停状态
WIFSTOPPED(status) 为非0,进程处于暂停状态
WSTOPSIG(status) 如果上述宏为真,取得使得进程暂停的那个信号的编号
WIFCONTINUED(status) 为真表示进程暂停后已经继续运行

waitpid函数

一次waitpid函数只能清除一个子进程,和wait函数类似

pid_t waitpid(pid_t pid,int* status,int options)

第一个参数用于指定需要回收的进程ID,第三个参数可以设置不阻塞回收,即仅仅返回一个状态

pid:

  • 大于0 表示回收的子进程ID
  • -1 表示回收任意子进程(相当于wait)
  • 0 回收当前调用waitpid一个组的任意子进程,在一般情况下和-1相同
  • <-1 回收指定进程组内的任意子进程,-进程组ID,进程组ID可以用ps ajx查看
    options:
  • 当参数为WNOHANG,非阻塞回收,轮询查看
  • 当参数为0的时候,阻塞回收,相当于wait

返回值:

  • 成功返回子进程ID
  • 失败返回-1
  • 如果轮询访问回收子进程的时候子进程没有结束则返回0
    例如:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>int main(int argc, char* argv[])
{int n=5;if(argc>2){printf("too many arguments\n");exit(1);}else if(argc==2){n = atoi(argv[1]);}int pi;pid_t p,q;for(pi=0;pi<n;++pi){p=fork();if(0 == p){break;}else if(3 == pi){q = p;}}if(n==pi){printf("I am parent,pid = %d\n",getpid());//删除单个子进程//waitpid(q,NULL,0);//循环删除子进程//while(-1!=waitpid(-1,NULL,0));//非阻塞删除子进程pid_t tid;do{tid=waitpid(-1,NULL,WNOHANG);}while(tid != -1);printf("OK\n");while(1);}else{printf("I am child,pid = %d\n",getpid());}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

string类的基本实现

https://blog.csdn.net/qq_29503203/article/details/52265829在面试中面试官常常会让你写出string类的基本操作&#xff0c;比如&#xff1a;构造函数&#xff0c;析构函数&#xff0c;拷贝构造等等.下面是除此之外的一些操作&#xff0c;希望可以帮助你更好的理解string以便以…

Python3常用数据结构

Python3中有三种组合数据类型&#xff0c;分别为&#xff1a; 序列类型&#xff1a;字符串&#xff08;str&#xff09;、元组&#xff08;tuple&#xff09;、列表&#xff08;list&#xff09;集合类型&#xff1a;集合&#xff08;set&#xff09;映射类型&#xff1a;字典…

Linux C++ 回射服务器

http://blog.csdn.net/qq_25425023/article/details/53914820回射服务器就是服务端将客户端的数据发送回去。我实现的回射服务器返回增加了时间。服务端代码&#xff0c;可以很容易看懂&#xff1a;[cpp] view plaincopy#include <sys/socket.h> #include <stdio.h&g…

TCP第四次挥手为什么要等待2MSL

当客户端进入TIME-WAIT状态的时候(也就是第四次挥手的时候)&#xff0c;必须经过时间计数器设置的时间2MSL(最长报文段寿命)后&#xff0c;才能进入关闭状态&#xff0c;这时为什么呢&#xff1f;&#xff1f;&#xff1f; 这最主要是因为两个理由&#xff1a; 1、为了保证客户…

计算机网络【一】概述+OSI参考模型

网络概述 局域网:覆盖范围小(100m以内)&#xff0c;自己花钱买设备&#xff0c;带宽固定(10M,100M,1000M)&#xff0c;自己维护&#xff08;接入层交换机直接连接电脑、汇聚层交换机直接连接接入层交换机&#xff09; 广域网:距离远&#xff0c;花钱买服务&#xff0c;租带宽&…

单链表逆序的多种方式

https://www.cnblogs.com/eniac12/p/4860642.htmltemplate<class T> void List<T>::Inverse() {if(first NULL) return;LinkNode<T> *p, *prev, *latter; p first->link;   // 当前结点prev NULL;   // 前一结点l…

Linux系统【四】进程间通信-管道

进程间通信&#xff08;IPC Interprocess Communication&#xff09; 进程和进程之间的通信只能通过内核&#xff0c;在内核中提供一块缓冲区进行通信。内核提供的这种机制叫做IPC 在进程间完成数据传输需要借助操作系统提供的特殊方法&#xff0c;如&#xff1a;文件&#xf…

单链表各种操作详解

#include "stdio.h" #include "stdlib.h"#define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0#define MAXSIZE 20 /* 存储空间初始分配量 */typedef int Status;/* Status是函数的类型,其值是函数结果状态代码&#xff0c;如OK等 */ typedef int…

Linux系统【五】进程间通信-共享内存mmap

mmap函数 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);参数&#xff1a; void *addr建立映射区的首地址&#xff0c;由Linux内核指定&#xff0c;所以我们直接传递NULL。也就是说虽然这是一个参宿但是并不…

socket编程 -- epoll模型服务端/客户端通信的实现

https://blog.csdn.net/y396397735/article/details/50680359 本例实现如下功能&#xff1a; 支持多客户端与一个服务端进行通信&#xff0c;客户端给服务端发送字符串数据&#xff0c;服务端将字符串中小写转为大写后发送回客户端&#xff0c;客户端打印输出经转换后的字符串。…

Python3 面向对象程序设计

类的定义 Python使用class关键字来定义类 class Car:def infor(self):print("This is a car") car Car() car.infor()内置方法isinstance()来测试一个对象是否为某个类的实例 self参数 类的 所有实例方法都有一个默认的self参数&#xff0c;并且必须是方法的第一…

计算机网络【二】物理层基础知识

计算机网络的性能 速率&#xff1a;连接在计算机网络上的主机在数字信道上传送数据位数的速率&#xff0c;也成为data rate 或bit rate&#xff0c;单位是b/s,kb/s,Mb/s,Gb/s。 我们平时所讲的宽带的速度是以字为单位的&#xff0c;但是实际中应用一般显示的是字节 &#xff0…

Linux网络编程——tcp并发服务器(多进程)

https://blog.csdn.net/lianghe_work/article/details/46503895一、tcp并发服务器概述一个好的服务器,一般都是并发服务器&#xff08;同一时刻可以响应多个客户端的请求&#xff09;。并发服务器设计技术一般有&#xff1a;多进程服务器、多线程服务器、I/O复用服务器等。二、…

求序列第K大算法总结

参考博客&#xff1a;传送门 在上面的博客中介绍了求序列第K大的几种算法&#xff0c;感觉收益良多&#xff0c;其中最精巧的还是利用快速排序的思想O(n)查询的算法。仔细学习以后我将其中的几个实现了一下。 解法 1&#xff1a; 将乱序数组从大到小进行排序然后取出前K大&a…

Linux网络编程——tcp并发服务器(多线程)

https://blog.csdn.net/lianghe_work/article/details/46504243tcp多线程并发服务器多线程服务器是对多进程服务器的改进&#xff0c;由于多进程服务器在创建进程时要消耗较大的系统资源&#xff0c;所以用线程来取代进程&#xff0c;这样服务处理程序可以较快的创建。据统计&a…

计算机网络【三】物理层数据通信

物理层传输媒介 导向传输媒体&#xff0c;比如光纤和铜线 双绞线&#xff08;屏蔽双绞线STP 五屏蔽双绞线UTP&#xff09;电线扭曲在一起可以降低互相之间的电磁干扰 同轴电缆 (50欧姆的基带同轴电缆&#xff0c;75欧姆的宽带同轴电缆) 10M和100M网络只使用了四根线&#xf…

02_算法分析

02_算法分析 0.1 算法的时间复杂度分析0.1.1 函数渐近增长概念&#xff1a;输入规模n>2时&#xff0c;算法A1的渐近增长小于算法B1 的渐近增长随着输入规模的增大&#xff0c;算法的常数操作可以忽略不计测试二&#xff1a;随着输入规模的增大&#xff0c;与最高次项相乘的常…

Linux网络编程——I/O复用之select详解

https://blog.csdn.net/lianghe_work/article/details/46506143一、I/O复用概述I/O复用概念&#xff1a;解决进程或线程阻塞到某个 I/O 系统调用而出现的技术&#xff0c;使进程不阻塞于某个特定的 I/O 系统调I/O复用使用的场合&#xff1a;1.当客户处理多个描述符&#xff08;…

Linux多进程拷贝文件

学习了mmap以后&#xff0c;实现一个简单的小程序&#xff0c;进行多个进程对一个文件进行拷贝。 Linux mmap共享内存学习可以参考我的另一篇博客&#xff1a;传送门 实现思想 我们可以将原来的文件利用mmap分成多个段分别进行传输。 实现代码 #include<stdio.h> #…

斐波那契查找(Fibonacci Search)和折半查找

两个查找算法都是针对有序数组进行查找&#xff0c;不同点在于分界点的取值不同。 算法介绍 折半查找很简单&#xff0c;每次与当前区间的中点进行比较&#xff0c;然后决定查找前一部分还是后一部分。 Fibonacci查找利用了Fibonacci序列每一项等于前两项和的特点进行划分&a…