进程组、进程组组长、会话的联系 实验

进程组、进程组组长、前后台进程组、会话之间的关系

graph LR
subgraph g1[会话]
subgraph g1_1[前台进程组]
subgraph g1_1_1[前台进程组组长进程]
end
subgraph g1_1_2[其他前台进程组进程...]
end
end
subgraph g1_2[后台进程组...]
end
end

如图所示:

  1. 每个进程组中有多个进程,只有一个进程组组长()
  2. 一个会话(session)中包含许多进程组,只有一个前台进程组。该会话中所有进程的sid都指向该前台进程组的组长进程。

基础概念

自动接受终端信号的组称为前台进程组
在终端通过 ctrl + c 等动作产生的信号首先被前台进程组接受
在 shell 启动的若干个进程组默认是父进程所在的组为前台进程组
除非是默认,否则都要通过调度才能成为前台进程组

随着而来的存在几个问题:

问题1: 前台进程组的组长和是否和会话(session)领头进程存在关系,比如该组的gpid == sid? (前台进程组组长是否等于会话领头进程)
问题2: 结合 孤儿进程实验 为什么当我们关闭远程终端连接之后,该终端创建的所有进程都会被杀死。

问题1

先说答案,前台进程组组长和会话领头进程确实有关,但进程组组长不是

进程组组长

我们可以直接使用ps命令

ps
ps -o pid -o pgid -o ppid -o sid

输出如下
image
(注意第二次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()创建了全新的会话,但是只能在子进程中创建。
image
该进程成为了全新会话的前台进程组长且。也是成了该会话的会话领头进程,其sid指向了自己。

问题2

我们干过一会儿会儿运维的都知道,关闭远程连接终端一定会导致其子进程被杀掉。但是根据孤儿进程的原理,子进程将会被托管给Init进程。
这是由于会话的机制导致的。
一般来讲除非创建会话,当前会话下创建的所有子进程都属于该会话,包括前台进程组和 后台进程组。当会话关闭后(注意不是会话领头进程死亡),会话下所有进程组将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。但是可以屏蔽,比如使用命令。

nohup command

原文链接: https://www.cnblogs.com/tofu-ran/p/17135475.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    进程组、进程组组长、会话的联系 实验

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/319163

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月24日 下午3:11
下一篇 2023年2月24日 下午3:12

相关推荐