linux内核——会话、进程组、线程组
会话、进程组、线程组总体关系示意图
待插入
Session(会话)与进程组
Shell 分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell可以同时运行一个前台作业和任意多个后台作业,这称为作业 控制(Job Control)。例如用以下命令启动5个进程(这个例子出自[APUE2e]):

其中proc1和proc2属于同一个后台进程组,proc3、proc4、proc5属于同一个前台进程组,Shell进程本身属于一个单独的进
程组。这些进程组的控制终端相同,它们属于同一个Session。当用户在控制终端输入特殊的控制键(例如Ctrl-C)时,内核会发送相应的信号(例如
SIGINT)给前台进程组的所有进程。各进程、进程组、Session的关系如下图所示。

现在我们从Session和进程组的角度重新来看登录和执行命令的过程。
1. getty或telnetd进程在打开终端设备之前调用setsid函数创建一个新的Session,该进程称为Session Leader,该进程的id也可以看作Session的id,然后该进程打开终端设备作为这个Session中所有进程的控制终端。在创建新 Session的同时也创建了一个新的进程组,该进程是这个进程组的Process Group Leader,该进程的id也是进程组的id。
2. 在登录过程中,getty或telnetd进程变成login,然后变成Shell,但仍然是同一个进程,仍然是Session Leader。
3.
由Shell进程fork出的子进程本来具有和Shell相同的Session、进程组和控制终端,但是Shell调用setpgid函数将作业中的某个
子进程指定为一个新进程组的Leader,然后调用setpgid将该作业中的其它子进程也转移到这个进程组中。如果这个进程组需要在前台运行,就调用
tcsetpgrp函数将它设置为前台进程组,由于一个Session只能有一个前台进程组,所以Shell所在的进程组就自动变成后台进程组。
在上面的例子中,proc3、proc4、proc5被Shell放到同一个前台进程组,其中有一个进程是该进程组的Leader,Shell调用
wait等待它们运行结束。一旦它们全部运行结束,Shell就调用tcsetpgrp函数将自己提到前台继续接受命令。但是注意,如果proc3、
proc4、proc5中的某个进程又fork出子进程,子进程也属于同一进程组,但是Shell并不知道子进程的存在,也不会调用wait等待它结束。
换句话说,proc3 | proc4 |
proc5是Shell的作业,而这个子进程不是,这是作业和进程组在概念上的区别。一旦作业运行结束,Shell就把自己提到前台,如果原来的前台进程
组还存在(如果这个子进程还没终止),则它自动变成后台进程组(回顾一下例 30.3 “fork”)。
下面看两个例子。

这个作业由ps和cat两个进程组成,在前台运行。从PPID列可以看出这两个进程的父进程是bash。从PGRP列可以看出,bash在id为
6994的进程组中,这个id等于bash的进程id,所以它是进程组的Leader,而两个子进程在id为8762的进程组中,ps是这个进程组的
Leader。从SESS可以看出三个进程都在同一Session中,bash是Session
Leader。从TPGID可以看出,前台进程组的id是8762,也就是两个子进程所在的进程组。

这个作业由ps和cat两个进程组成,在后台运行,bash不等作业结束就打印提示信息[1] 8835然后给出提示符接受新的命令,[1]是作业的编号,如果同时运行多个作业可以用这个编号区分,8835是该作业中某个进程的id。请读者自己分析ps命令的输出结果。
2.2. 与作业控制有关的信号
我们通过实验来理解与作业控制有关的信号。

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

jobs命令可以查看当前有哪些作业。fg命令可以将某个作业提至前台运行,如果该作业的进程组正在后台运行则提至前台运行,如果该作业处于停止状
态,则给进程组的每个进程发SIGCONT信号使它继续运行。参数%1表示将第1个作业提至前台运行。cat提到前台运行后,挂起等待终端输入,当输入
hello并回车后,cat打印出同样的一行,然后继续挂起等待输入。如果输入Ctrl-Z则向所有前台进程发SIGTSTP信号,该信号的默认动作是使
进程停止。

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

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

SIGKILL信号既不能被阻塞也不能被忽略,也不能用自定义函数捕捉,只能按系统的默认动作立刻处理。与此类似的还有SIGSTOP信号,给一个
进程发SIGSTOP信号会使进程停止,这个默认的处理动作不能改变。这样保证了不管什么样的进程都能用SIGKILL终止或者用SIGSTOP停止,当
系统出现异常时管理员总是有办法杀掉有问题的进程或者暂时停掉怀疑有问题的进程。
上面讲了如果后台进程试图从控制终端读,会收到SIGTTIN信号而停止,如果试图向控制终端写呢?通常是允许写的。如果觉得后台进程向控制终端输出信息干扰了用户使用终端,可以设置一个终端选项禁止后台进程写。

首先用stty命令设置终端选项,禁止后台进程写,然后启动一个后台进程准备往终端写,这时进程收到一个SIGTTOU信号,默认处理动作也是停止进程。
进程组与线程组
进程可有多线程组成,同一个进程的各个线程属于统一个线程组,每个线程对应于一个轻量级进程,他们的tgid就是领头线程或进程的pid,getpid()返回的是tgid。
进程与线程组的关系可详见我的另一片博文《linux内核——进程,轻量级进程,线程,线程组》
linux内核——会话、进程组、线程组的更多相关文章
- 深入Linux内核架构——进程管理和调度(上)
如果系统只有一个处理器,那么给定时刻只有一个程序可以运行.在多处理器系统中,真正并行运行的进程数目取决于物理CPU的数目.内核和处理器建立了多任务的错觉,是通过以很短的间隔在系统运行的应用程序之间不停 ...
- 24小时学通Linux内核之进程
都说这个主题不错,连我自己都觉得有点过大了,不过我想我还是得坚持下去,努力在有限的时间里学习到Linux内核的奥秘,也希望大家多指点,让我更有进步.今天讲的全是进程,这点在大二的时候就困惑了我,结果那 ...
- Linux下的进程与线程(二)—— 信号
Linux进程之间的通信: 本文主要讨论信号问题. 在Linux下的进程与线程(一)中提到,调度器可以用中断的方式调度进程. 然而,进程是怎么知道自己需要被调度了呢?是内核通过向进程发送信号,进程才得 ...
- (转)Linux内核之进程和系统调用
Linux内核之进程和系统调用 什么是系统调用 在Linux的世界里,我们经常会遇到系统调用这一术语,所谓系统调用,就是内核提供的.功能十分强大的一系列的函数.这些系统调用是在内核中实现的,再通过一定 ...
- Linux内核之进程地址空间
Linux内核之进程地址空间 内核中的函数以相当直接了当的方式获得动态内存: __get_free_pages 或 alloc_pages从分区页框分配器中获得页框; kmem_cache_alloc ...
- Linux内核之进程和文件共享
1.Shell命令的执行和进程 Shell 命令可以是内部或者外部命令. 内部(内置)命令(internal (built-in) command)的代码本身就是shell进程的一部分.L ...
- Linux查看某个进程的线程
线程是现代操作系统上进行并行执行的一个流行的编程方面的抽象概念.当一个程序内有多个线程被叉分出用以执行多个流时,这些线程就会在它们之间共享特定的资源(如,内存地址空间.打开的文件),以使叉分开销最小化 ...
- 深入理解Linux内核-进程
1.进程的静态特性 进程:程序执行时的一个实例 进程描述符(task_struct): 进程的基本信息(thread_info).指向内存区描述符的指针(mm_struct).进程相关的tty(tty ...
- Linux内核之进程(1)
进程:程序执行的一个实例,在Linux源代码中,常把进程称为任务(task)或者线程(thread). 从内核观点来看,进程的目的是担当分配系统资源(CPU的时间.内存等)的实体. 当一个进程创建时, ...
随机推荐
- iOS Core Animation 动画 入门学习(一)基础
reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide ...
- Codeforces Round #245 (Div. 2) C. Xor-tree DFS
C. Xor-tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/430/problem/C ...
- luoguoj 1598 垂直柱状图 模拟
P1598 垂直柱状图 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.luogu.org/problem/show?pid=1598 ...
- Ubuntu 16.04安装cuda7.5 GCC
http://www.linuxidc.com/Linux/2017-01/139320.htm 在介绍Ubuntu 16.04安装 CUDA7.5开始前,先辨析几个概念GPU.NVIDIA.NVID ...
- Java:Spi 小实战
背景 Java 中区分 Api 和 Spi,通俗的讲:Api 和 Spi 都是相对的概念,他们的差别只在语义上,Api 直接被应用开发人员使用,Spi 被框架扩张人员使用,详细内容可以看:http:/ ...
- android——根据MVC框架设计的结构
- 使用NSHashTable存储引用对象
NSHashTable 我们使用集合(NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,NSSet,NSMutableSet)存储对象时会 ...
- 【GISER&&Painter】Chapter02:WebGL中的模型视图变换
上一节我们提到了如何在一张画布上画一个简单几何图形,通过创建画布,获取WebGLRendering上下文,创建一个简单的着色器,然后将一些顶点数据绑定到gl的Buffer中,最后通过绑定buffer数 ...
- 海思hi3518 移植live555 实现H264的RTSP播放
用海思的交叉编译工具交叉编译live555 ,结合海思例子venc中的H264部分,完成RTSP的视频数据发布. 用vlc可以播放,但是实时性比较差,慢了5秒
- JS是否存在方法重载
java里面是存在重载的,那么js中呢?这个问题面试的时候会经常遇到.但是可以肯定的说,js中是不存在重载的,但是我们可以通过其他的方式来模拟重载,我们可以通过argument方法来实现. argum ...