进程间关系
进程组
每个进程都有自己的进程ID,除此之外,每个进程也都属于一个进程组。
进程组是一个进程或者多个进程的集合。
通常他们和同一个作业有联系,可以接受来自同一个终端的信号。
每一个进程组都有一个组ID,这个ID就是该进程组组长的进程ID
组长进程可以创建一个进程组,并创建该组中的进程。
当一个进程组中的所有进程死亡时,该进程组才会终止。
当一个进程组的组长死亡时,只要有其他进程存在,则该进程组存在。并且组ID仍是已故的组长进程ID。
作业
Shell通过前台和后台来分别控制前台作业和后台作业。这称为作业控制
Shell可以同时运行一个前台作业和多个后台作业。
一个作业可以由多个进程构成
作业和进程组的区别
当一个作业H中的某个进程A创建了一个子进程后B,这个进程B不属于作业H;然而进程A和进程B都属于同一个进程组
当前台作业运行结束后,Shell就把自己提到前台。如果前台作业的某个子进程还没有终止,则它自动变为后台进程
一般情况下,作业和进程组可以不做区分,但是我们要知道他们的不同之处是什么。
查看后台作业
jobs
将前台作业提至后台
bg 1(作业号) 先要contrl C终止后台作业
将后台作业提至前台
fg 1(作业号)
区别验证
fork出一个子进程后,如果将父进程退出,则前台作业结束
子进程会以后台进程的身份继续运行
此时,我们用Ctrl+C无法终止该子进程(因为CTRL+C只可以终止前台作业)
代码
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid = fork();//创建子进程
while(1)
{
if(pid < 0)
{
perror("fork");
return -1;
}
else if(pid == 0)
{
printf("子进程在运行\n");
sleep(1);
}
else
{
printf("父进程结束\n");
exit(0);
}
}
return 0;
}
运行结果
会话
会话(Session)是一个或多个进程组的集合。
一个会话可以有一个控制终端。
这通常是登陆到其上的终端设备(在终端登陆情况下)或伪终端设备(在网络登陆情况下)。
建立与控制终端连接的会话首进程被称为控制进程。
一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。
所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。
新打开一个终端即新建立一个会话的过程。关闭一个终端,即关闭一次会话 ,其中所有的作业,进程组都不存在了。
proc1 | proc2 | proc3 &
proc4 | proc5
其中proc1与proc2和proc3属于同一个后台进程组,proc4和proc5属于同一个前台进程组
Shell本身属于一个单独的进程组。
这些进程组的控制终端相同,它们同属于一个会话,当用户在控制终端输入特殊的控制键(如Ctrl+C,产生SIGINT,Ctrk+,产生SIGQUIT,Ctrl+Z,
产生SIGTSTP),内核发送相应的信号给前台进程组中的所有进程。
终端
终端的基本概念
在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端 (Controlling Terminal)
控制终端是保存在PCB中的信息,而我们知道fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。
默认情况 下(没有重定向)
每个进程的标准输入、标准输出和标准错误输出都指向控制终端,进程从标准输入读也就是读用户的键盘输入,进程往标准输出或标准错误输出写也就是输出到显示器上。
此外在控制终端输入一些特殊的控制键可以给前台进程发信号,例如Ctrl-C表示SIGINT,Ctrl-\表示SIGQUIT。
如何查看终端
每个进程都可以通过一个特殊的设备文件/dev/tty访问它的控制终端。 ttyname函数可以由文件描述符查出对应的文件名,该文件描述符必须指向一个终端设备而不 能是任意文件。
在一个终端上打开
在另一个终端上打开