会话:
会话就是多个进程组的组合。
会话首进程:
一个会话里是有很多进程的,第一个被创建出来的进程就是会话首进程。
会话ID:
会话首进程一般都是登录shell(假设我们在终端运行程序的情况下,至于为什么是shell我会在最后补充),也一定是组长进程,也就是它的进程ID等于它的进程组ID,同时这两个ID和会话ID也相等,所以要获取会话ID等同于获取另外两个ID。
进程组:
几个进程组队在一起就成了一个进程组,每个进程都有一个进程组ID属性,同一进程组中的进程的进程组ID相同。
组ID:
一个进程组一定有一个组长,一般是进程组中第一个被创建出来的进程,你也可以自行更改。组长进程的进程ID一定等于进程组ID,这就是判断是否是组长进程的方法。
举个例子:一个公司创业,首先是一个人,然后慢慢加了几个人,做大以后有了部门,每个部门各司其职。这里公司就是一个会话,创业者就是会话首进程,公司名就是会话id;各个部门就是进程组,各个部门的名字就是组id;员工就是进程,工号就是进程id(当员工辞职后工号会留下来给新任员工,对比进程id)
额外补充:
linux下我们一般都在shell中运行程序,假如你键入了你的程序名,那么shell会fork一个子进程来执行你的程序,一般这个程序也是在前台运行的,shell自己则到后台去了,等你的程序运行完退出后shell就又回到前台了,这就是一个会话,里面有shell和你的程序,因为shell是第一个被创建出来的,所以它的进程ID或进程组ID就是此次的会话ID,验证的方法就是你在程序中调用tcgetsid函数和调用getppid函数的输出结果是一样的
关于创建守护进程fork两次的原因如下:
第一次fork前:在开始运行且fork之前拥有一个会话两个进程组:shell拥有一个进程组,你运行的程序拥有一个进程组,且他们都是组长进程;shell还是会话首进程
第一次fork后:父进程的退出带来的变化是告知shell命令已完成;新创建的子进程不可能是组长进程(因为父进程在它之前创建)。这为接下来调用setsid做准备(因为调用setsid()的进程不能是组长进程)
第二次fork原因:在调用setsid()后,原来的子进程现在在一个新会话里面,新会话里有一个进程组并且它就是组长进程。而且如果原来有终端现在也分离了。然而问题就处在这里,组长进程是有可能获得终端的,为了防止它以后获得终端,所以再次fork来消除潜在问题
阅读(2140) | 评论(0) | 转发(0) |