简介:这讲解进程之间的关系:父子进程、进程和进程组、会话。这节只需要了解即可。
1: 首先、讲解一下终端登录。
在早期的时候、我们使用终端设备进行登录,但是由于终端设备连接的有限,因此登录的用户也就是有限的。随着位映射图形终端变得可用,开发出了窗口系统,它向用户提供了与主机
系统进行交互的新方式。在这里、我简单介绍一下过去有终端设备登录的流程(只是做为一个了解)。
首先是init进程读取/etc/ttys文件(此文件保存各个终端设备的信息),为每一个终端创建一个空的环境。然后使用getty函数以读写的方式打开终端,并将标准输入、输出和错误
重置到该终端中,最后执行login程序进行登录。
2:这里简单介绍一下进程组的概念。
每一个进程都属于一个进程组,每个进程组有类似与进程ID的进程组ID。进程组的存在方便我们管理控制。在上一节中、我们介绍回收进程的时候,可以等待指定进程组ID中的进程结束。
有些时候,我们可能需要很多个进程合作去完成某一项任务。这时候,我们可以使用进程组的概念去会后进程组中的进程。下面我简单列举一个例子。
多进程服务器:每当一个客户端到来的时候、我们创建一个新的进程去执行相应的任务。当执行完任务后,子进程就会向父进程发送终止信号,这时候、我峨嵋你不清楚是该进程组中的那个进程结束了。因此、我们可以选择去回收该进程组中的进程。
我们可以使用如下函数获取和设置进程ID。
int setpgid(pid_t pid, pid_t pgid);
此函数用于将指定进程ID设置为pgid,但是这个函数只能为自己或者对应的子进程设置进程组ID,同时、如果子进程使用了exec函数后就不能设置进程组ID。
如果你想要父子进程同属一个进程组,那么请在fork之后使用此函数设置进程组ID。
int getpgid(pid_t pid);
获取指定进程ID的进程组ID。
注:只要进程组中有一个进程存在,那么该进程组就存在。(因此、在这里我们觉得进程组ID是这进程创建终止而随时变化的。
3:会话
会话的概念倒是十分简单、他就是几个进程组的集合。
会话是没有会话ID的,通常我们可以获得该进程的首个进程组的进程组ID。
通常情况下、我们可以fork一个子进程去调用如下的函数以保证改进程和其他进程没有什么关系(除了、父进程是init进程)。
pid_t setsid(void);
将调用该函数的进程设置为一个会话。在调用此函数后、改进程会发生如下情况。
a)改进程成为一个会话的首进程。
b)该进程是一个新的进程组的组长进程。
c)如果改进程之前和控制终端有联系的话,那么现在改进程和控制终端将不会有什么联系。
pid_t getsid(pid_t pid);
此函数用于获取指定进程所处会话首个进程组的进程组ID。
4:控制终端。
会话和进程组有一些其他的恶行:
a:一个会话可以有一个控制终端。这通常是登录到其他的终端设备或伪终端设备。
b:建立与控制终端连接的进程称为伪终端进程。
c:一个会话中可以分为前台进程组和后台进程组。
d:如果一个会话有一个控制终端,则它有一个前台进程组,会话中的其他进程组则为后台进程组。
e:信号会发送给前台进程组。
如下两个函数用于通知内核哪一个是前台进程组。
pid_t tcgetpgrp(int filedes);//用于将filedes先关联的终端设备前台进程组的进程组ID。