会话:
是一个或多个进程组的集合。
通常是由shell管道将几个进程编成一组,比如 proc1 | proc2 &
进程调用setsid函数建立一个新会话。如果调用此函数的进程不是一个进程组的组长,此函数创建一个新会话,该进程会变成新会话的的会话首进程(session leader),此时,该进程是新会话中的唯一进程,该进程成为新进程组的组长进程,新进程组ID是该调用进程的进程ID,该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,这种联系也被切断。
如果该调用进程已经是一个进程组的组长,则此函数返回出错,为了保证不出现这种情况,通常先调用fork,然后使父进程终止,而子进程继续,因此子进程继承了父进程的进程组ID,而其进程ID则是新分配的,两者不可能相等,这就保证了子进程不是一个进程组的组长。
控制终端:
会话和进程组还有一些其他特性:
一个会话可以有一个控制终端(controlling terminal)
建立与控制终端连接的会话首进程被称为控制进程
一个会话的几个进程组可被分成一个前台进程组以及一个或多个后台进程组。
无论何时键入终端的中断键,都会将中断信号发送至前台进程组的所有进程
无论何时键入终端的退出键,都将退出信号发送至前台进程组的所有进程
通常不用担心控制终端,登陆时,将自动建立控制终端。
函数tcgetpgrp、tcsetpgrp和tcgetsid
需要有一种方法来通知内核哪一个进程组是前台进程组,这样终端设备驱动程序就知道将终端输入和终端产生的信号发送到何处。
作业控制:
它允许在一个终端上启动多个作业(进程组),它控制哪个作业可以访问该终端以及哪些作业在后台运行,作业控制要求以下三种形式的支持。
1.支持作业控制的shell
2.内核中的终端驱动程序必须支持作业控制
3.内核必须提供对某些作业控制信号的支持
孤儿进程组:
如果一个进程,fork了一个子进程然后终止,如果子进程也停止,将如何?子进程如何继续,以及子进程是否知道自己是孤儿进程。
在fork之后,父进程沉睡5s,这是一种让子进程在父进程终止之前运行的一种权宜之计,当父进程终止后,子进程成为孤儿进程,所以父进程ID成为1,也就是init进程。那么子进程成为一个孤儿进程组的成员
孤儿进程组:该组的每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。