进程组、进程组组长、前后台进程组、会话之间的关系
subgraph g1[会话]
subgraph g1_1[前台进程组]
subgraph g1_1_1[前台进程组组长进程]
end
subgraph g1_1_2[其他前台进程组进程...]
end
end
subgraph g1_2[后台进程组...]
end
end
如图所示:
- 每个进程组中有多个进程,只有一个进程组组长()
- 一个会话(session)中包含许多进程组,只有一个前台进程组。该会话中所有进程的sid都指向该前台进程组的组长进程。
基础概念
自动接受终端信号的组称为前台进程组
在终端通过 ctrl + c 等动作产生的信号首先被前台进程组接受
在 shell 启动的若干个进程组默认是父进程所在的组为前台进程组
除非是默认,否则都要通过调度才能成为前台进程组
随着而来的存在几个问题:
问题1: 前台进程组的组长和是否和会话(session)领头进程存在关系,比如该组的gpid == sid? (前台进程组组长是否等于会话领头进程)
问题2: 结合 孤儿进程实验 为什么当我们关闭远程终端连接之后,该终端创建的所有进程都会被杀死。
问题1
先说答案,前台进程组组长和会话领头进程确实有关,但进程组组长不是
进程组组长
我们可以直接使用ps命令
ps
ps -o pid -o pgid -o ppid -o sid
输出如下
(注意第二次ps的pid和第一次不一样因为它们是不同的进程)
其中ps进程的sid和其pgid并不相等。但是其ppid等于会话进程的pid
原因很简单,虽然这两个进程在同一会话,但是其并不在同一进程组。因此进程组组长和会话领头进程并没有直接关系。
前台进程组组长
接下来,我们创建一个全新的会话,打印一下当前进程的pid、ppid、pgid、sid.
pid_t ret = fork();
if (ret == -1) { return -1; }
if (ret > 0) { exit(0); }
sleep(1);
ret = setsid();
printf("% s(% d) :< % s> pid=%d ppid=%d pgid=%d sid=%dn", __FILE__, __LINE__, __FUNCTION__, getpid(), getppid(), getpgid(getpid()), getsid(getpid()));
该代码创建了全新的会话,打印了当前会话进程的信息。注意setsid()创建了全新的会话,但是只能在子进程中创建。
该进程成为了全新会话的前台进程组长且。也是成了该会话的会话领头进程,其sid指向了自己。
问题2
我们干过一会儿会儿运维的都知道,关闭远程连接终端一定会导致其子进程被杀掉。但是根据孤儿进程的原理,子进程将会被托管给Init进程。
这是由于会话的机制导致的。
一般来讲除非创建会话,当前会话下创建的所有子进程都属于该会话,包括前台进程组和 后台进程组。当会话关闭后(注意不是会话领头进程死亡),会话下所有进程组将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。但是可以屏蔽,比如使用命令。
nohup command
原文链接: https://www.cnblogs.com/tofu-ran/p/17135475.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/319163
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!