日期:2014-05-16 浏览次数:20839 次
每个进程除了有一个进程ID之外,还属于一个进程组。进程组是一个或多个进程的集合。通常他们与同一作业相关联,可接受来自同一终端的各种信号。
#include<unistd.h>
pid_tgetpgrp(void); /* POSIX.1version */
pid_t getpgid(pid_tpid);
intsetpgid(pid_t pid, pid_t pgid);
函数getpgrp返回调用进程的进程组ID。
getpid函数也有此功能。
进程可以通过调用setpgid来加入一个现有的组或创建一个新进程组。
会话是一个或多个进程组的集合。
通常是由shell的管道将几个进程编成一组的。如下所示:
proc1 | proc2 &
proc3 | proc4 | proc5
其会话安排如下:
进程调用setsid函数建立一个新会话。
#include <unistd.h>
pid_t setsid(void);
还可调用getsid来返回会话首进程的进程组ID
#include <unistd.h>
pid_t getsid(pid_t pid);
登录时,将自动创建控制终端。
程序与控制终端交互时,为保证程序能读写控制终端的方法是打开文件/dev/tty。在内核中,词特殊文件是控制终端的同义语。如果程序没有控制终端,则打开此设备将失败。
1. 一个会话可以有一个控制终端
2. 建立与控制终端联结的会话收进程被称为控制进程
3. 一个会话中的几个进程组可被分成一个前台进程组以及一个或几个后台进程组
4. 如果一个会话有一个控制终端,则它有一个前台进程,会话中的其他进程组则为后台进程组
5. 无论何时键入终端的中断键,就会将中断信号发送给前台进程组的所有进程
6. 无论何时键入终端的退出键,就会将退出信号发送给前台进程组的所有进程
7. 如果终端接口检测到的调制解调器已经断开网络,则将挂断信号发送给控进程。
#include <unistd.h>
pid_t tcgetpgrp(int fd);
int tcsetpgrp(int fd, pid_t pgrp);
tcgetpgrp函数返回调用前台进程的进程组ID,该前台进程组与在fd上打开的终端相关联。
如果进程有一个控制终端,则该进程可以调用tcsetpgrp将前台进程组ID设为pgrp,fd必须引用该会话的控制终端。
#include<termios.h>
pid_ttcgetsid(int fd);
该函数识别出控制终端的会话首进程的会话ID。
作业控制允许在一个终端上启动多个作业(进程组),他控制哪个作业可以访问终端,以及那些作业也在后台运行。
catchen123@ubuntu:~$ cat > temp.foo & 在后台启动,但将从标准输入读
[1] 3894
chen123@ubuntu:~$
键入回车
[1]+ Stopped cat > temp.foo
chen123@ubuntu:~$fg %1 使1号作业成为前台作业
cat >temp.foo shell告诉我们现在哪一个作业在前台
hello,world 输入1行,后面接文件结束符(ctrl+D)
chen123@ubuntu:~$cat temp.foo 检查该行已送入文件
hello,world
chen123@ubuntu:~$
shell在后台启动cat进程,但是当cat视图读其标准输入时,终端驱动程序知道他是个后台作业,于是将SIGTTIN信号送至该后台作业。shell检测到其子进程的状态改变,并通知我们该作业已被停止。然后,我们用shell的fg 将此停止的作业送入前台运行。这样做可以使shell将此作业置入前台进程组,并将继续信号送给进程组。因为该作业现在位于前台进程组中,所以它可以读控制终端。
chen123@ubuntu:~$ cat temp.foo & 在后台执行
[1] 4125
chen123@ubuntu:~$hello,world
[1]+ Done cat temp.foo
chen123@ubuntu:~$stty tostop
chen123@ubuntu:~$cat temp.foo &
[1] 4129
chen123@ubuntu:~$