APUE 2 - 进程组(process group) 会话(session) job

 

进程组(process group)html

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

 1 #include <unistd.h>
 2 
 3 /*
 4 返回调用进程的进程组Id
 5 */
 6 pid_t getpgrp(void);
 7 
 8 /*
 9 若pid为0,做用与getpgrp相同
10 */
11 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:session

1 #include <unistd.h>
2 
3 /*
4 设置pid所在进程组Id为pgid
5 */
6 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)指一个或多个进程组的集合。spa

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

proc1 | proc2 &
proc3 | proc4 | proc5

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

进程能够经过setsid来建立新的session。htm

1 #include <unistd.h>
2 
3 /*
4 成功,返回进程组ID,不然返回 -1
5 */
6 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:
1 #include <unistd.h>
2 
3 /*
4 获取pid所在session的session leader
5 的Process Group ID
6 */
7 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设置前台进程组:

 1 #include <unistd.h>
 2 
 3 /*
 4 经过打开终端的文件描述符获取前台进程组Id
 5 */
 6 pid_t tcgetpgrp(int fd);
 7 
 8 /*
 9 pgrpid 必须是相同session中的一个进程组Id
10 */
11 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 &
[1]    1475
$ pr *.c | lpr &
[2]    1490
终端驱动可识别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系统底层开发应该是不可或缺的。
相关文章
相关标签/搜索