(一)进程组
每个进程除了有一个进程ID之外,还属于一个进程组。进程组是一个或多个进程的集合。通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID。每个进程组都可以有一个组长进程。组长进程的标识是其进程组ID等于其进程ID。 组长进程可以创建一个进程组,创建该组中的进程,然后终止。只要在某个进程组中一个进程存在,则该进程组就存在,这与其组长进程是否终止无关。
总结
(二)作业
Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,Shell 可以运行一个前台作业和任意多个后台作业,这称为作业控制 。
作业与进程组的区别:如果作业中的某个进程又创建了子进程,则子进程不属于作业。
一旦作业运行结束,Shell就把自己提到前台(子进程还在,可是子进程不属于作业),如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。
我们在重新理解一下,在前台新起作业,shell是无法运行,因为他被提到了后台。 但是如果前台进程退出,shell就又被提到了前台,所以可以继续接受用户输入
下面再来验证父进程创建子进程,当父进程退出,但是子进程不属于当前作业,则bash将自己提至前台运行,而将子进程放置到后台。
1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 pid_t id=fork();
6 if(id<0)
7 {
8 perror("fork");
9 return 1;
10 }
11 else if(id==0)//child
12 {
13 while(1)
14 {
15 printf("i am child\n");
16 sleep(1);
17 }
18 }
19 else//father
20 {
21 int count=5;
22 while(count--)
23 {
24 printf("i am father\n");
25 sleep(1);
26 }
27 }
28
29 return 0;
30 }
我们可以看到其一直在向前台打消息,子进程所属的进程组的组长(父进程)已经退出,但是此进程组还在,想要干掉这个进程,kill -9 即可
(三)会话
会话(Session)是一个或多个进程组的集合。 一个会话可以有一个控制终端。这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在⺴网络登陆情况下)。建立与控制终端连接的会话首进程被称为控制进程。一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。 所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组 ,会话即新打开一个终端
以上用如下关系可以表示:
(四)实验
(五)总结
jobs命令可以查看当前有哪些作业。
fg命令可以将某个作业提至前台运行,如果该作业的进程组正在后台运行则提至前台运行,如果该作业处于停止状态,则给进程组的每个进程发SIGCONT信号使它继续运行。
参数 1表示将第1个作业提至前台运行。cat提到前台运行后,挂起等待终端输入,当输入hello并回车后,cat打印出同样的一行,然后继续挂起等待输入。如果输入Ctrl-Z则向所有前台进程发SIGTSTP信号,该信号的默认动作是使进程停止,cat继续以后台作业的形式存在。
bg命令可以让某个停止的作业在后台继续运行,也需要给该作业的进程组的每个进程发SIGCONT信号。cat进程继续运行,又要读终端输入,然而它在后台不能读终端输⼊入,所以又收到SIGTTIN信号而停止。
对应进程间关系,就这么多的东西,希望大家一起进步!!!
只有不停的奔跑,才能不停留在原地!!!