分类: LINUX
2008-12-09 13:39:09
进程组是一个或多个进程的集合,通常用于作业控制;
组长是创建进程组的进程。进程组ID(PGID)等于组长的PID。
设置和获取PGID:
#include
pid_t getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);
setpgid(2)只能用于进程自身或其尚未执行exec的子进程:当pid==pgid时,使PID为pid的进程成为所在进程组的组长;pid==0时,使调用此函数的进程成为组长;pgid==0时,使进程的PID成为PGID。
会话是一个或多个进程组的集合,建立新会话的函数是:
#include
pid_t setsid(void);
调用成功时,调用进程成为一个新进程组的组长,并返回其PGID(即进程自己的PID);
进程组组长不能新建会话,执行setsid(2)时将返回-1;
如果进程拥有控制终端,执行setsid(2)后将被断开;
#include
pid_t getsid(pid_t pid);
该函数根据指定的进程返回其SID,要求指定的进程属于调用者所在的会话。从取值上看,SID等价于会话首进程的PID同时也等价于首进程的PGID;
一个会话可以有一个控制终端。根据控制终端引入了控制进程(与控制终端建立了连接的进程,即会话首进程)、前台进程组(拥有控制终端的进程组,一个会话最多只有一个)、后台进程组(一个会话中无控制终端的其它进程组)等概念;
进程通过打开/dev/tty来建立与控制终端的连接:
#include
pid_t tcgetpgrp(int filedes);
int tcsetpgrp(int filedes, pid_t pgrpid);
tcgetpgrp(3)返回拥有控制终端的控制进程的PID(即前台进程组的PGID),tcgetpgrp 设置所打开终端的前台进程组,用于获得tty。其中,参数filedes为所打开的tty的文件描述符;
一个作业通常即是一个进程组,几个进程之间通过管道线连接以完成所需任务。
在shell中,直接输入命令则启动一个前台作业,如果该命令行以&结尾则启动为后台作业。如:
以管道线创建一个前台作业:
$ tail -f /var/log/apache2/access.log | grep GET | grep http.*admin.*.php
创建一个后台作业:
$ find / -mount -type f -perm -4000 -ls | awk {'print $3, $5, $6, $NF'} > /mnt/usb/setuidfiles &
若要将前台作业转为后台进行,键入Ctrl + Z,此时作业处于暂停状态。
查看当前的后台作业状态使用jobs(1)命令。
使后台暂停的作业继续执行使用bg(1)命令,使后台作业在前台执行使用fg(1)命令。
只有前台作业可以接受终端的输入。后台作业需要接受输入时,通过捕捉信号SIGTTIN信号而挂起,此时shell将在标准输出上报告其作业状态(stopped);但后台作业可以对终端输出,通过stty(1)命令可改变其设置,使其在需要执行输出时暂停(信号SIGTTOU),并在shell上报告作业状态。
也可以通过重定向stdout和stderr使后台作业不向终端执行输出,如:
$ make > /dev/null 2>&1 &
定义为:该组中每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。
或者:一个进程组不是孤儿进程组的条件是:该组中存在一个进程,其父进程在同一会话的其它进程组中。
孤儿进程组将被置于后台执行。