我目前正在将进程组实现到我的操作系统项目的POSIX子系统中.但是,我对POSIX规范(setsid)(以及维基百科的进程组页面)感到有些困惑.
我们的终端层将SIGINT发送到前台进程(组,其id应该等于组长的PID).在这种情况下,该前台进程(我们的"登录"应用程序)通过调用成为组长setsid
.当用户登录时,程序会分叉并执行用户的shell.在这个阶段,我的理解是我setpgid
在打电话之前给分叉的孩子打电话exec*
.这意味着执行的程序从一开始就是过程组的一部分.
如果我想在进程组之外运行新分叉的子进程,我只能setsid
在调用之前调用分叉的子进程exec*
.
它是否正确?我应该检查或做的是否有任何非常模糊的东西?
作为一个后续问题,我相信我已经知道,是否需要fork
转移团体会员资格?或者是setpgid
每次fork
通话后必须使用的东西?我收集的进程组是fork
从POSIX定义转移的fork
.
提前致谢.
Jon*_*ler 15
有趣的问题 - 尤其是因为它长期没有得到部分答案.
来自POSIX定义部分的一些引用:
3.290过程组
允许发出相关进程信号的进程集合.系统中的每个进程都是由进程组ID标识的进程组的成员.新创建的进程加入其创建者的进程组.
3.291进程组ID
表示进程组生命周期内的唯一正整数标识符.
注意:另请参阅进程ID重用中定义的进程组ID重用.
3.292流程组负责人
进程ID与进程组ID相同的进程.
3.293流程组生命周期
创建进程组时开始的时间段,并且当组中的最后一个剩余进程离开组时结束,这是由于最后一个进程的生命周期结束或者调用setsid()的最后一个剩余进程或setpgid()函数.
注意:setsid()和setpgid()函数在POSIX.1-2008的系统接口卷中详细定义.
[...]
3.337会议
为工作控制目的而建立的一组进程组.每个进程组都是会话的成员.进程被视为其进程组所属的会话的成员.新创建的进程加入其创建者的会话.进程可以改变其会话成员资格; 见setsid().同一会话中可以有多个进程组.
注意:setsid()函数在POSIX.1-2008的系统接口卷中详细定义.
3.338会议负责人
已创建会话的进程.
注意:有关详细信息,请参阅POSIX.1-2008的系统接口卷中定义的setsid()函数.
3.339会话生命周期
创建会话与保留为会话成员的所有进程组的生命周期结束之间的时间段.
名称
setsid - 创建会话并设置进程组ID
概要
Run Code Online (Sandbox Code Playgroud)#include <unistd.h> pid_t setsid(void);
描述
如果调用进程不是进程组领导者,则setsid()函数将创建新会话.返回时,调用进程应该是该新进程的会话负责人,应该是新进程组的进程组负责人,并且没有控制终端.调用进程的进程组ID应设置为等于调用进程的进程ID.调用进程应该是新进程组中的唯一进程,也是新进程中唯一的进程.
和:
名称
setpgid - 设置作业控制的进程组ID
概要
Run Code Online (Sandbox Code Playgroud)#include <unistd.h> int setpgid(pid_t pid, pid_t pgid);
描述
setpgid()函数应连接现有进程组或在调用进程的会话中创建新进程组.
会话负责人的进程组ID不得更改.
成功完成后,具有与pid匹配的进程ID的进程的进程组ID应设置为pgid.
作为一种特殊情况,如果pid为0,则应使用调用进程的进程ID.此外,如果pgid为0,则应使用指示进程的进程ID.
如定义所示,会话可以包含多个进程组.在广泛的限制范围内,流程可能会更改流程组(尽管它在任何时候都只属于一个流程组).会话处理的选项更加有限; 基本上,一个进程要么仍然是其原始会话的成员,要么它可以使自己成为新会话的领导者.
复制问题的部分内容:
我们的终端层将SIGINT发送到前台进程(组,其id应该等于组长的PID).在这种情况下,该前台进程(我们的"登录"应用程序)通过调用setsid成为组长.当用户登录时,程序会分叉并执行用户的shell.在这个阶段,我的理解是我在调用exec*之前从forked子调用setpgid.这意味着执行的程序从一开始就是过程组的一部分.
我怀疑括号应该是'前台进程组(其id应该等于组长的PID)'.根据定义(3.292),进程组负责人是其PID与进程组ID相同的进程.我没有引用相关材料,但我相信将信号发送给流程组负责人是正确的
请注意,前台进程通过调用成为会话负责人setsid()
,也成为进程组负责人.我希望登录程序在分叉之后但在执行shell之前将用户的shell设置为进程组负责人(可能还有会话负责人).所有子进程都自动从其父进程继承进程组和会话; 如果你想要它不同,你必须覆盖它.
如果我想在进程组之外运行新分叉的子进程,我只能在调用exec*之前调用forked子进程中的setsid.
你可以这样做,但它也会创建一个新的会话.您可能希望使用setpgid()
(现代标准;可能setpgrp()
是SVID的旧标准)而不是setsid()
.
它是否正确?我应该检查或做的是否有任何非常模糊的东西?
是的,这大多是正确的.是的,可能还有一些不起眼的东西要跟踪.例如,您可能需要考虑控制TTY.
作为一个后续问题,我相信我已经知道,是否需要fork来转移组成员身份?或者是每次fork调用后必须使用setpgid完成的事情?我收集进程组是通过fork从POSIX定义fork转移的.
子进程fork()
属于同一组(如/etc/group
),也属于同一会话和同一进程组 - 但它不是会话负责人,也不是进程组负责人.