进程分类

一、僵尸进程

1. 产生原因

子进程退出为了保存退出状态,退出资源后不会被完全释放,等待父进程来获取退出状态,然后释放子进程所有资源。父进程已收到子进程结束的消息,没有明确的答复操作系统内核,此时操作系统内核会一直保存该子进程的部分PCB信息,同时将进程的状态置为defunct,这个子进程将会成为僵尸进程,占着系统资源不释放。通过ps -ef | grep "xxx"找到僵尸进程的PID,通过kill -9 PID不能强制杀死,僵尸进程是不能够被直接消除掉

2. 危害

占用PCB资源(主要是PID资源),系统将会因为产生大量的僵尸进程,而没有可用的进程号来产生新进程,导致系统资源不足,普通进程可能无法创建。

3. 示例

#include <stdio.h>                           
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>

int main()
{
	uint64_t i = 0;

	int id = -1;
	id = fork();
	if (id < 0)
	{
		return -1;
	}
	else if (id == 0)
	{
		sleep(30);
		exit(0);
	}
	while (1)
	{
		sleep(1);
		i++;
	}
	return 0;
}

4. 解决方案

父进程的知道子进程的结束,并且明确的回复操作系统,此时操作系统才能回收PCB资源,避免僵尸进程的产生,此时父进程需要处理子进程的结束,需要调用wait()、waitpid()函数族,wait()会等待子进程的结束,调用wait()的进程会阻塞,直到接收到子进程的消息才被唤醒;子进程结束时,会给父进程发送SIGCHLD(17)信号

(1)wait():只能在父子进程中,父进程等待子进程的结束,一直在阻塞,信号通知父进程,避免了子进程的僵尸状态,wait()方法只能在具有子进程的进程中使用,如果一个进程没有子进程,调用wait()方法会失败,wait()方法是用于处理子进程结束状态的,同时让父进程明确告知操作系统内核已经处理了子进程的结束,从而使得操作系统能够彻底回收子进程的PCB信息

(2)僵尸进程的父进程exit()结束掉,此时僵尸进程被init进程接收;init进程会查看进程状态,发现是僵尸进程,就会通知操作系统将其回收

(3)写一个信号处理函数,signal(SIGCHLD,  函数指针),当子进程结束时,信号处理函数接收到SIGCHLD信号时,方才调用wait(),使父进程长时间的阻塞,父进程结束,即可解决父进程的阻塞,又可避免僵尸进程的产生

二、孤儿进程

当父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程,由于进程不可能脱离进程树而独立存在,孤儿进程将被init进程(进程号为1)所收养,并由 init 进程对它们完成状态收集工作,孤儿进程被收养后进行正常的释放,没有危害

#include <stdio.h>                              
#include <unistd.h>

int main()
{
	int id = fork();

	if (id < 0)
	{
		return -1;
	}
	else if (id == 0)
	{
		while (1)
		{
			sleep(1);
		}
	}
	return 0;
}

三、几个概念

1. 进程组

在Linux下进程除了具有父子关系这样的组织关系以外,还具有分组的组织关系。任何一个进程都需要隶属于某个进程组,每一个进程组都拥有一个独立的进程组编号,可以通过getpgid()方法得到。每一个进程组都拥有且只拥有一个组长进程。可以通过该组长管理其组内的其他进程的统一行为,用 setpgid() 创建。

2. 前台进程组

前台进程组是和终端服务进程、bash进程捆绑在一起的,和终端直接相关。那么,终端的任何操作都会影响到所有的前台进程组,在shell交互环境中执行一个命令,就会产生一个新的进程来执行这个命令,不仅如此,还会产生一个新的进程组,该进程组的组长就是被执行命令而形成的新进程,前台进程组的最大问题就在于:由终端控制,终端只需要让进程组的组长停止,其组内的所有进程都会停止。

3. 后台进程组

断开与终端的关系(并非输入、输出、错误输出关系),进程组关系,不再受制于终端而存在,这种进程与进程组被称之为后台的,后台进程存在的理由:需要常驻内存,提供一个服务。

4. 会话

是进程组之间的某种关系,即每一个进程除了要归属于一个进程组以外,还需要归属于一个会话之中,会话的概念主要是从终端登陆到计算机之后得到的。当一个终端登录到计算机之后,为了方便将不同的终端隔离开,同时又能够充分合理的管理一个终端下产生的所有进程,因此而提出了会话的概念。换句不准确描述来说:会话就是用户登录之后从登录服务进程到shell进程所组成的集合,一个会话通常是由多个进程组组成的,分为两部分(前台进程组,后台进程组),会话具有一个会话首进程。操作系统通过会话的首进程来管理整个会话中的所有进程组。用setsid()方法来创建一个新的会话,从而就会出现新的进程组。

四、守护进程

1. 概念

守护进程也称为精灵进程,是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理发生的事件,守护进程不受用户登陆与注销的影响,它一直在运行着。Linux下的大多数服务器都是利用守护进程实现的。

2.创建守护进程 

  • 创建一个新的会话
  • 构成孤儿进程

3. 总结

  • 守护进程自成会话,自称进程组。
  • 守护进程不受用户登陆,注销的影响。
  • 守护进程一般与控制终端无关。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值