Linux--进程间关系/终端/作业控制

一、进程间关系(3种)

1.进程组

每个进程除了有一个进程ID之外,还属于一个进程组。进程组是一个或多个进程的集合。通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组都有一个唯一的进程组ID。每个进程组都可以有一个组长进程。组长进程标识的是,其进程组ID等于其进程ID(一般,默认每一组的第一个进程为组长进程)。组长进程可以创建一个进程组,创建该组中的进程,然后终止。

注意:只要在某个进程组中一个进程存在,则该进程组就存在,这与其组长进程是否终止无关。

实例如下:


通过上图,有以下几点说明:

(1)‘&’:表示将进程组放在后台执行

(2)这里的进程有:2570、2571、2572

(3)进程组组长:2570(默认情况下为进程组当中的第一个进程)

(4)ps的选项:

         a:不仅列出当前用户的进程,也列出所有其他用户的进程

         x:不仅列出有控制终端的进程,也列出所有无控制终端的进程

         j:列出与作业控制相关的信息

(5)kill  -9:可以杀掉组长进程,但是该进程组还在(我们来验证一下这个结论,如下图)


2.作业

(1)Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。

(2)作业控制:一个前台作业可以由多个进程组成,一个后台也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业。

(3)作业与进程组的区别:如果作业中的某个进程又创建了子进程,则该子进程不属于作业,但属于该进程组。

(4)一旦作业运行结束,Shell就会把自己提到前台(虽然子进程还在,但是该子进程不属于作业)。如果原来的前台进程还存在(该子进程还没有终止),它会自动变为后台进程。

(5)查看后台作业:jobs

        将前台作业提至后台:bg 2(2为作业号)先要Ctrl C终止后台作业

        将后台作业提至前台:fg 2

如果我们在前台新起一个作业,则Shell是无法在前台运行的(Shell只可以运行一个前台作业),此时,它被提到了后台。当前台进程退出时,Shell就又被提到了前台,可以继续接受用户的输入。

下面,我们来看两个例子。

例一:


我们来看一下运行结果:


由此,我们可以验证上面我们所说的结论。

fork出一个子进程后,父进程先退出,作业结束,该进程组还在,Shell成为前台作业,子进程跑去后台,成为后台进程组,Ctrl C终止不了。

那该怎么终止该进程呢?

使用ps,查看该进程的PID,使用kill -9 (进程id号)杀掉该进程。

注意:由于子进程在后台每一秒运行一次,我们在敲命令的时候手速太慢,可能会出现乱码的情况(这只是在我们看来是乱码的),操作系统不会这么认为,别慌,将命令敲进去就好了!

例二:


运行结果:


说明:如果作业中的某个进程又创建了子进程,则该子进程不属于作业但属于该进程组,如果父子进程同时在前台运行,Ctrl C可以终止父子进程。这里需要注意的是,Ctrl C是在向前台进程组发送信号,而不是向作业发送信号。

3.会话

会话(Session)是一个或多个进程组的集合。一个会话可以有一个控制终端。这通常是登录到其上的终端设备(在终端登录情况下)或伪终端设备(在网络登陆情况下)。建立与控制终端连接的会话首进程被称为控制进程。一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。所以一个会话中,应该包括控制进程(会话首进程),一个前台该进程组和任意后台进程组。

新打开一个终端:


其中,SID:会话id(这里的会话id是3244),四个进程都属于同一个进程组(3405),同一个会话(3244)

但是,这些进程的父进程也就是PPID(3244)是谁呢?我们在这里并没有创建进程啊!我们来看看


现在,我们就知道了,这里的3244是bash!也就是我们的解释器,会话首进程,而且这几个进程的父进程都是bash

(细心的读者可能会发现,这里的怎么是-bash啊,出现-bash的原因是在网络中登录)


二、终端

1.终端的基本概念 

(1)Shell进程的控制终端 (Controlling Terminal):在UNIX系统中,用户通过终端登录系统后得到一个Shell进程。控制终端是保存在PCB中的信息,而我们知道fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。默认情况下(没有重定向)。

每个进程的标准输入、标准输出和标准错误输出都指向控制终端,进程从标准输入读也就是读用户的键盘输入,进程往标准输出或标准错误输出写也就是输出到显示器上。另外,在控制终端输入一些特殊的控制键可以给前台进程发信号(例如Ctrl C表示SIGINT,Ctrl \表示SIGQUIT)。

2.每个进程都可以通过一个特殊的设备文件/dev/tty来访问它的控制终端。 

ttyname函数可以由文件描述符查出对应的文件名,该文件描述符必须指向一个终端设备而不 能是任意文件。

查看终端对应的设备:


终端:


三、作业控制

(1)Session与进程组“Shell可以同时运行一个前台进程和任意多个后台进程”其实是不全面的,现在我们来研究更复杂的情况。事实上,Shell分前后台来控制的不是进程而是作业(Job)或者是进程组(Process Group)。

(2)作业控制(Job Control):一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell可以同时运行一个前台作业和任意多个后台作业。(前面也说了这个概念,这里我们再一次加深印象)


注意:这里我们来看‘&’观察该进程在前台还是后台

通过上图的我们不难发现:Ctrl C杀掉的不是进程,而是作业!

(3)作业有关的控制信号

通过下图我们来理解与作业控制有关的信号


将cat放到后台运行,由于cat需要读标准输入(也就是终端输入),而后台进程是不能读终端输入的,因此内核发SIGTTIN信号给进程,该进程的默认处理动作是使进程停止。


(1)jobs命令可以查看当前有哪些作业。

(2)fg命令可以将某个作业提至前台运行,如果该作业的进程组正在后台运行,则提至前台运行,如果该作业处于停止状态,则给进程组的每个进程发SIGCONT信号使它继续运行。

(3)cat提到前台后,挂起等待终端输入,当输入heihei并回车后,cat打印出来同样的一行,然后继续挂起等待输入。如果输入Ctl Z,则向所有前台进程发SIGTSTP信号,该信号的默认处理动作是使进程停止,cat继续以后作业的形式存在。

(4)bg命令可以让某个停止的作业在后台继续运行,也需要给该作业的进程组的每个进程发SIGCONT信号。cat进程继续运行,又要读终端输入,然而它在后台不能读终端输入,所以又要收到SIGTTIN信号而停止。


用kill命令给一个停止的进程发SIGTERM(15)信号,这个信号并不会立刻处理,而要等进程准备继续运行之前处理,默认动作是终止进程。但如果给一个停止的进程发SIGKILL信号就不同了。

因此,可以得出结论,后台进程不能从终端下读取数据。

其实,后台进程也不能在终端写数据(因为后台程序,stdin/stdout/stderr三个输入输出的管道都被屏蔽了)。

猜你喜欢

转载自blog.csdn.net/cherrydreamsover/article/details/79974333