进程组(process group)

进程组顾名思义是指一个或多个进程的集合。他们通常与同一个job(可以从同一个终端接收信号)相关联。每个进程组拥有一个唯一的Process Group Id。可以使用getpgrp或getpgid获取进程的Process Group Id:

 #include <unistd.h>

 /*
返回调用进程的进程组Id
*/
pid_t getpgrp(void); /*
若pid为0,作用与getpgrp相同
*/
pid_t getpgid(pid_t pid);

每个进程组可以有一个进程组leader,leader的进程Id与其进程组id相同。无论进程组leader是否终止,只要进程组中存在未终止的进程这个进程组就不会消失。进程组leader终止后进程组中便不存在进程组leader,它不会自动推选新的进程组leader。参见:Must a process group have a running leader process?

可以通过setpgid函数设置进程组Id:

 #include <unistd.h>

 /*
设置pid所在进程组Id为pgid
*/
int setpgid(pid_t pid, pid_t pgid);

调用进程只能设置他自己和他的子进程的Process Group Id,并且如果他的子进程调用了exec类函数,那么调用进程也无法更改它的这个子进程的Process Group Id。在 job-control shells中,这个方法常用于fork调用后父进程来设置子进程的Process Group Id,或者子进程设置它自己的Process Group Id。当然,fork调用后子进程是会继承父进程的Process Group Id的,fork后setpgid目的是为了确保子进程的Process Group Id而避免因为并发竟态导致的意外(这个地方不太懂,没构建出作者设想的竟态环境)。

会话(session)

会话(session)指一个或多个进程组的集合。

上图所示的session结构可以使用shell中的pipeline来表示:

proc1 | proc2 &
proc3 | proc4 | proc5

在上面示例中,login shell所在的进程组和proc1、proc2所在的进程组为后台进程组, proc3,proc4,proc5所在的进程组为前台进程组。一个会话中只能有一个前台进程组,可以有一个或多个后台进程组。关于前台进程组与后台进程组我们在后面介绍。

进程可以通过setsid来创建新的session。

 #include <unistd.h>

 /*
成功,返回进程组ID,否则返回 -1
*/
pid_t setsid(void);

setsid函数成功时返回的是调用进程的Process Group Id,也是调用进程的Process Id, 因为session leader 永远是它所在的进程组leader。其实UNIX中是没有类似 Process Id 或 Process Group Id 的 "Session Id" 这个东西的,有的仅仅是"Session leader"。 我们可以认为 session leader 的 Process Group Id 或 Process Id为其所在 session 的 Session Id。

setsid在调用时有3件事会发生:
  • 调用进程成为新session的session leader(A session leader is the process that creates a session)。此时此进程是新session中的唯一进程。
  • 调用进程成为新进程组的leader。新进程组的Process Group ID 等于 调用进程的 Process ID。
  • 调用进程不会再有控制终端。如果调用进程在调用setsid前拥有控制终端的话,那么调用setsid后他将断开与其控制终端的联系。
进程组leader不可以调用setrsid,如果调用者是进程组leader,那么setsid会返回一个error(大概因为一个进程不可以是两个进程组的leader?)。为了保证setsid的调用者不是进程组Id,许多实现通过调用fork,然后终止父进程,使子进程继续执行。我们可以保证此时子进程不会是任何进程组的leader。因为子进程继承父进程的进程组,而子进程的Process Id 是新产生的,因此子进程的Process Id 不可能与其继承的Process Group Id 相同。
可以通过getsid函数获取session leader 的 Process Group Id:
 #include <unistd.h>

 /*
获取pid所在session的session leader
的Process Group ID
*/
pid_t getsid(pid_t pid);

控制终端(controlling terminal)

session和进程组还有其他几个特性:
  • 一个session可以拥有一个控制终端(当然也可以没有)。他通常是我们登录时的终端设备或伪终端。
  • 创建与控制终端的链接的session leader被称为控制进程 (Controlling Process)。
  • 一个会话中的进程组可以划分为一个前台进程组和一个或多个后台进程组。
  • 如果一个会话拥有控制终端,那么它有一个前台进进程组,这个会话中的其他进程组都是后台进程组。
  • 无论何时我们按下终端的中止键(通常是 DELETE或Crtl-C),就会有一个中止信号发送给前台进程组中的所有进程。
  • 无论何时我们按下终端的退出键(通常是Crtl-Backslash),就会有一个退出信号发送给前台进程组中的所有进程。
  • 如果终端接口检测到网络断开,那么hang-up信号就会发送给控制进程,即the session leader。
下图描述了这些特性:

一般我们不必关心控制终端,它在我们登录时自动被创建。有事程序需要与控制终端通信,无论是使用标准输出还是标准输入重定向。程序保证与控制终端进行通信的方法时读写 /dev/tty文件。这个特殊文件在内核中是控制终端的代名词。如果程序没有控制终端,那么它打开/dev/tty文件将会失败。
可以使用tcgetpgrp函数获取前台进程组Id,使用tcsetpgrp设置前台进程组:

 #include <unistd.h>

 /*
通过打开终端的文件描述符获取前台进程组Id
*/
pid_t tcgetpgrp(int fd); /*
pgrpid 必须是相同session中的一个进程组Id
*/
int tcsetpgrp(int fd, pid_t pgrpid);

关于session、process group、controlling terminal的更多信息 , 参见:The controlling-terminal and process-groups.

Job Control

job control 允许我们在一个终端中启动多个job,我们可以控制哪些job可以接触到终端,哪些在后台运行。job control 要求3中形式的支持:
  1. shell需要支持job control
  2. 内核中的终端驱动必须支持job control
  3. 内核必须支持确定的job-control信号
对我们而言,当我们在shell中使用job control时,我们可以在前台或后台启动job。一个job仅仅是一些进程的集合,通常是一些使用pipeline连接的进程。
例:
# 在前台启动包含一个进程的job
vi main.c
# 两个后台jobs调用的所有进程都是后台进程
pr *.c | lpr &
make all & # 当我们启动一个后台job时,shell会给这个job分配一个job id,
# 并打印这个job中的一个或多个进程IDs
$ make all > Make.out &
[]
$ pr *.c | lpr &
[]
终端驱动可识别3种特殊字符以产生发送给前台进程组的信号:
  • 中止字符(通常是DELETE或Crtl-C)产生SIGINT
  • 退出字符(通常是Crtl-Backslash)产生SIGQUIT
  • 暂停字符(通常是Crtl-Z)产生SIGSTP

如前所述,只有前台job会接收到终端输入,但是后台job尝试读取终端并不是错误的,终端驱动会检测后台进程的这种举动并向后台job发送一个特殊的信号:SIGTTIN。SIGTTIN通常会中止后台job。

总结

    前面我们讨论了进程组、会话、前台进程组、后台进程组、控制终端、job control 这些unix系统息息相关的概念。通过这些知识我们可以了解到Unix系统中程序的工作模式及与用户的交互方式。我们甚至可以推测从unix系统启动到shell的正常运行及shell中启动其他进程的过程中系统中发生的一些事情。这些对于unix系统底层开发应该是不可或缺的。

APUE 2 - 进程组(process group) 会话(session) job的更多相关文章

  1. 进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端

    摘要:本文主要介绍进程的基本属性,基本属性包含:进程ID.父进程ID.进程组ID.会话和控制终端. 进程基本属性 1.进程ID(PID) 函数定义:      #include <sys/typ ...

  2. Oracle11gR2设置连接数process与会话session值

    近日构建的Web应用用户数量有所上升,后台总是打印无法打开数据库连接的错误信息: 000000a3 SystemOut O 9月 ::, ERROR - msg:打开数据库出错. 经查询发现需要更改数 ...

  3. Linux进程组和会话

    Linux的进程相互之间有一定的关系.比如说,在Linux进程基础中,我们看到,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构.我们在这里讲解进程组和会话,以便以更加丰富的方式了 ...

  4. Linux-进程、进程组、作业、会话、控制终端详解

    一.进程 传统上,Unix操作系统下运行的应用程序. 服务器以及其他程序都被称为进程,而Linux也继承了来自unix进程的概念.必须要理解下,程序是指的存储在存储设备上(如磁盘)包含了可执行机器指 ...

  5. linux系统编程--守护进程,会话,进程组,终端

    终端: 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中,控制终端是保存在PCB中的信息,而f ...

  6. 进程 、进程组、会话、控制终端之间的关系 (转载 http://blog.csdn.net/yh1548503342/article/details/41891047)

    一个进程组可以包含多个进程 进程组中的这些进程之间不是孤立的,他们彼此之间或者存在者父子.兄弟关系,或者在功能有相近的联系. 那linux为什么要有进程组呢?其实提供进程组就是方便管理这些进程.假设要 ...

  7. linux内核之进程的基本概念(进程,进程组,会话关系)

    进程是操作系统的一个核心概念.每个进程都有自己唯一的标识:进程ID,也有自己的生命周期.一个典型的进程的生命周期如图4-1所示. 进程都有父进程,父进程也有父进程,这就形成了一个以init进程为根的家 ...

  8. (七) 一起学 Unix 环境高级编程(APUE) 之 进程关系 和 守护进程

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  9. 【MPI学习7】MPI并行程序设计模式:MPI的进程组和通信域

    基于都志辉老师MPI编程书中的第15章内容. 通信域是MPI的重要概念:MPI的通信在通信域的控制和维护下进行 → 所有MPI通信任务都直接或间接用到通信域这一参数 → 对通信域的重组和划分可以方便实 ...

随机推荐

  1. TCP常见的定时器三次握手与四次挥手

    1.TCP常见的定时器 在TCP协议中有的时候需要定期或者按照某个算法对某个事件进行触发,那么这个时候,TCP协议是使用定时器进行实现的.在TCP中,会有七种定时器: 建立连接定时器(connecti ...

  2. python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性

    先介绍几个类中的应用__getattr__,__setattr__,__get__,__set__,__getattribute__,. __getattr__:当在类中找不到attribute的时候 ...

  3. Java面向对象之抽象类,接口

    抽象类: 含有抽象方法的类被声明为抽象类 抽象方法由子类去实现 含有抽象方法的类必须被声明为抽象类 抽象类被子类继承,子类(如果不是抽象类)必须重写抽象类中的所有抽象方法 抽象方法: 声明而未被实现的 ...

  4. win10 设置默认输入法为英文,ctrl +shift切换中文

    控制面板-更改输入法,这个界面出现的是电脑现在安装的语言,每个语言中可能有多个输入法,比如我的有微软的和qq的,谁在上谁就是系统的默认语言(本人当然是中文在上),英文中有美式键盘. 如果想要电脑启动的 ...

  5. linux基础(五)

    一.linux网络原理及基础设置 ifconfig 命令:显示所有正在启动的网卡的详细信息或设定系统中网卡的IP地址. [root@bogon ~]# ifconfig ens33: flags=41 ...

  6. 【NOI复习】树链剖分

    简介 树链剖分通常用来解决一类维护静态树上路径信息的问题, 例如:给定一棵点带权树, 接下来每次操作会修改某条路径上所有点的权值(修改为同一个值或是同加上一个值等) , 以及询问某条路径上所有点的权值 ...

  7. 关于MUI集成微信分享遇到的坑

    今天聊一下MUI这个框架吧! 首先,用这个框架也有很长一段时间了,项目不同,涉及到的功能也有不同,之前没有涉及到微信分享相关的内容!今天,遇到了,也解决了,分享出来. 下面是手顺: 1.分享的代码是参 ...

  8. [BZOJ 3319] 黑白树

    3319: 黑白树 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 557  Solved: 194[Submit][Status][Discuss] ...

  9. 一步一步深入理解Dijkstra算法

    先简单介绍一下最短路径: 最短路径是啥?就是一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第 ...

  10. WinFrom通过委托传递事件

    今天一个功能需要动态创建pictruebox然后根据时间来倒叙显示,一开始对于这个需求摸不着头脑,后来在公司的大神帮助下实现了,话不多说具体实现上代码了: 1.动态添加控件并倒叙 首先添加一个用户控件 ...