Linux中的进程关系详解
2015-11-07 21:19
423 查看
进程组的概念
每一个进程除了有一个进程ID之外,还属于一个进程组,进程组通常是一个或多个进程的集合。这些进程通常是与一个作业相关的。例如:ps axu|grep bash|wc -l 这是三个进程,他们直接通过管道传递数据,为了是完成一个作业,对于这个整体来说是一个进程组,其中ps进程是进程组的组长进程。进程组也是由一个id来标识进程组的,通过使用PGID来标识,然而这个PGID==进程组组长进程的PID的使用下面的这个命令来验证这一事实:[root@localhost common]# ps -o pid,ppid,pgid,sid,comm|more PID PPID PGID SID COMMAND 2445 2441 2445 2445 bash 3882 2445 3882 2445 ps 3883 2445 3882 2445 more ps 是其中的第一个进程,也是这个进程组的组长进程,那么其 PID==PGID==2882 more和ps是同一个进程组的,因为其PGID相同
相关的系统API
下面这两个方法是用来设置和获取进程组的方法#include <unistd.h> int setpgid(pid_t pid, pid_t pgid); 如果pid等于pgid,那么pid就成为了其所属的进程组的组长进程, 如果pid等于0,则标识把当前进程设置为pgid的组长进程 如果pgid等于0,则使用pid作为目标pgid pid_t getpgid(pid_t pid); //这个方法的使用很简单,这里不做介绍
下面是一个测试的例子,在这个例子显示出一个只有单个进程的进程组
#include <unistd.h> #include <stdio.h> int main() { printf("%d\n",getpgid(getpid())); while(1); } 测试结果如下: a.out属于4082这个进程组的,并且是组长进程 [root@localhost ~]# ps -o pid,ppid,pgid,sid,comm a PID PPID PGID SID COMMAND 1698 815 1698 1698 bash 2445 2441 2445 2445 bash 4082 2445 4082 2445 a.out 4087 4083 4087 4087 bash 4206 4087 4206 4087 ps
可以看出正常情况下,直接运行的进程通常是一个新进程组的组长进程,与这个进程有通信的,或者是这个进程派生的都属于这个进程组.
会话的概念
会话就是一些有关联的进程组的集合而已.概念上来说其实不是很难理解,下面是一个展示会话其含义的例子:[root@localhost ~]# ps -o pid,ppid,pgid,sid,comm|more PID PPID PGID SID COMMAND 4087 4083 4087 4087 bash 4521 4087 4521 4087 ps 4522 4087 4521 4087 more 再次使用这个例子,ps 和more进程是一个进程组,bash进程属于另外一个进程组,bash执行了ps和more进程,所以这两个进程组存在关联,属于一个会话。其中SID代表这个会话的ID,从上面的结果可以看书,ps more bash是两个进程组的,但是都是一个会话的。会话ID,为首领进程组的组长进程的PID,
相信通过上面的这个例子,你应该对会话有了一个新的概念了吧.
相关的系统API
用于设置和获取session id的API#include <unistd.h> pid_t getsid(pid_t pid); //获取指定进程的sid pid_t setsid(void); 1.不能由进程组的组长进程调用,否则会产生错误 2.非进程组的组长进程调用将会创建会话并且会产生下面的效果: 1.调用进程成为会话的首领,此时该进程是新会话的唯一成员 2.新建一个进程组,其PGID为其PID,该进程成为该组的组长进程 3.调用进程讲脱离终端(守护进程中常用)
一个错误使用setsid的例子
#include <unistd.h> #include <stdio.h> int main() { setsid(); perror("setsid error"); while(1); } setsid error: Operation not permitted [root@localhost ~]# ps -o pid,ppid,pgid,sid,comm a PID PPID PGID SID COMMAND 1698 815 1698 1698 bash 2445 2441 2445 2445 bash 4087 4083 4087 4087 bash 4960 2445 4960 2445 a.out 4961 4087 4961 4087 ps
上面的例子会执行失败,其执行失败的原因在于执行这个程序后,这个程序是一个进程组的组长进程,组长进程是无法调用setsid的.下面的例子是一个正确使用setsid的例子:
#include <unistd.h> #include <stdio.h> int main() { if(fork > 0) //父进程等待 while(1); else{ //子进程,创建会话,并创建一个新的进程组成为组长进程 setsid(); while(1) } } PID PPID PGID SID COMMAND 5070 2445 5070 2445 a.out 5071 5070 5071 5071 a.out
上面的例子中通过在子进程中调用setsid成功创建了一个新的会话,和新的进程组,并且成为了新进程组的组长进程以及会话的领导进程组.子进程之所以可以成功创建会话是因为父进程是进程组的组长进程,子进程只是属于这个进程组中的一个进程而已,除此之外什么也不是,所以这个子进程具备setsid的使用条件.
会话和终端的关系
一个会话可以有一个控制终端(controlling terminal)。建立与控制终端连接的会话首进程被称为控制进程(controlling process)。
一个会话中的几个进程组可被分成一个前台进程组(forkground process group)和几个后台进程组(background process group)。
如果一个会话有一个控制终端,则它有一个前台进程组。
无论何时键入终端的中断键(DELETE或Ctrl+C),就会将中断信号发送给前台进程组的所有进程。
无论何时键入终端的退出键(Ctrl+),就会将退出信号发送给前台进程组的所有进程。
如果终端检测到调制解调器(或网络)已经断开连接,则将挂断信号发送给控制进程(会话首进程)。
相关文章推荐
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区