********************************************************************************************************************************************************
一、进程组
进程组:一个或多个进程的集合。
每个进程都可以有一个组长进程;
组长进程的标识:它的进程ID==进程组的ID;
**********************************************************************************************
*********************************************
*************
二、作业
Shell分前后台来控制的不是进程而是作业或进程组,Shell可以运行一个前台作业和任意多个后台作业,这叫作业控制。
一个前台作业可以由多个进程组成,一个后台进程也可以由多个进程组成
一旦作业运行结束(作业中的所有进程也都将结束),
Shell
就把自己提到前台,如果原来的作业中的某个前台进程的子进程还存在(子进程不属于作业,所以不会随着作业结束而结束)
,它自动变为后台进程组。
**********************************************************************************************************
*********************************************
*
作业与进程组的区别:如果作业中的某个进程由创建了子进程,则子进程不属于作业
*******************************************************************************************************
*********************************************
****
三、会话
会话:一个或多个进程组的集合;开启一个终端就是在建立一个会话的过程。
一个会话可以有一个控制终端;
建立与控制终端连接的会话首进程被称为控制进程(bash)。
一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。
所以一个
会话中,应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组。
内核发送相应的信号给前台进程组中的所有进程。
*******************************************************************************************************
*********************************************
****
四、setpgid 和tcsetpgrp 函数
setpgid:
shell
调用setpgid函数将作业中的某个子进程指定为一个新进程组的 Leader,然后调 用setpgid 将该作业中的其它 子进程也转移到这个进程组中。
(在 shell 命令行启动的进程是 shell 的子进程,原本
应该具有与 shell 相同的会话、进程组和控制终端;但实际上子进程却不在 shell 的进程组中,原因就是 shell 调用了
该函数,所以 bash 是自成一个进程组的)。
这就解释了,为什么在shell下启动一个进程(该进程有 fork出的子进程),bash 所在的进程组与 该进程的不一样(当然该进程与它的子进程在同一进程组)。
tcsetpgrp :将处于后台的进程组提至前台运行 。
*******************************************************************************************************
*********************************************
****
五、作业控制
1、以 cat 命令为例(把它放到后台,从终端读):
(1)
由于
cat
需要读标准输入
(
也就是终端输入
),
而后台进程是不能读终端输入
的
,
因此内核发
SIGTTIN
信号给进程
,
该信号的默认处理动作是使进程停止。
(2)
jobs
命令:可以查看当前后台有哪些作业。
fg
命令:可以将某个作业提至前台运行
:
a、如果该作业的进程
组正在后台运行则提至前台运行;
b、如果该作业处于停止状态
,
则给进程组的每个进程发
SIGCONT
信号使它继续行。
参数
%1
表示将第
1
个作业提至前台运行。
cat
提到前台运行后
,
挂起等待终端输入
,
当 输入
hello
并回车后
,cat
打印出同样的一行
,
然后继续挂起等待输入。
紧接着, 如
果输入
Ctrl-Z
则向所有前 台进程发
SIGTSTP
信号
,
该信号的默认动作是使进程停止,
cat
继续
以后台作业的形式存在。
(3)
bg
命令:可以让某个停止的作业在后台继续运行
,
也需要给该作业的进程组的每个进程发
SIGCONT
信号。
cat
进程继续运行
,
又要读终端输入
,
然而它在后台不能读终端输入
,
所以又收
到
SIGTTIN
信号而停止。
2、给一个停止的进程发SIGTERM与SIGKILL信号的区别:
(1)用
kill
命令给一个停止的进程发
SIGTERM
信号
,
这个信号并不会立刻处理
,
而要等进程准备
继续运行之前处理
,
默认动作是终止进程。
(2)但如果给一个停止的进程发
SIGKILL
信号就不同了。
SIGKILL信号既不能被阻塞也不能被忽略 ,也不能用自定义函数捕捉
,
只能按系统的默认动作
立刻处理(SIGSTOP 信号也与此类似)。(
这样保证了不管什么样的
进
程都能用
SIGKILL
终止或者用
SIGSTOP
停止
,
当系统出现异 常时管理员总是有办法杀掉有问题的进程或者暂时停掉怀疑有
问题的进程。)
3、后台
进程往终端写,是可以的,但它会扰乱前台进程的运行;
1)、fork 出的子进程属于父进程所在的进程组,但不在父进程所在的作业;
2)、一旦父进程退出,前台作业结束,shell被提至前台,但子进程仍在继续,所以子进程会被切入到后台,但它仍会往前台打印消息;
3)、与此同时,shell在前台的运行就会受到干扰
可以
用
#stty tostop命令,可以禁止后台进程往终端写,但将后台进程提至前台后,它便会开始运行,并完成退出。
*******************************************************************************************************
*********************************************
****