setpgid()的第一个参数可以是会话领导者还是组长?

时间:2018-05-29 19:39:00

标签: c linux process

来自Linux编程接口

#include <unistd.h>
int setpgid(pid_t  pid , pid_t  pgid );
     

pid参数可能未指定作为会话领导者的进程。违反   此规则导致错误EPERM。

  1. 为什么pid成为会话领导者?
  2. pid可以成为小组组长吗?为什么?

    如果是,则在致电setpgid()之后,其他进程将在该组中最初进行处理 最初由流程pid领导的是:

    • gid为pid的原始群组,现在已丢失流程pid且没有群组负责人,或
    • 进程pgid的新组pid更改为?

    我怀疑第一个可能与本书为setsid()描述的内容相矛盾:

      

    对进程组负责人能够调用setsid()的限制是必要的,因为没有它,进程组负责人将能够将自己置于另一个(新)会话中,而进程组的其他成员仍然在原来的会议。 (不会创建新的流程组,因为根据定义,流程组负责人的流程组ID已经与其流程ID相同。)这将违反严格的两级会话层次结构和进程组,进程组的所有成员必须属于同一会话。

  3. 感谢。

    一些相关问题Can a leader of a process session or group leave for another existing session or group?

2 个答案:

答案 0 :(得分:2)

会话负责人始终是流程组负责人。如果您要将其移至另一个流程组,则它将不再是流程组负责人,这违反了上述规则。

答案 1 :(得分:2)

此行为由POSIX指定(这意味着它适用于调用自身的所有内容&#34; Unix&#34;而不仅仅是Linux)。 http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html说:

ERRORS
    [EPERM] The process indicated by the pid argument is a session leader.

规范并未说明为什么存在此规则,但我相信dbush所说的理由是正确的:会话领导者必须始终是流程组负责人;如果它可以进入另一个进程组,它将不再是一个进程组组长,违反了不变量。

但是,只是流程组负责人而非会话负责人的流程可能将自己置于另一个流程组(不再是流程组负责人),然后可能会自行退出进程组的成员再次成为进程组的领导者。在某些情况下,作业控件shell实际上来执行此操作:请注意规范的RATIONALE部分底部的位

  

setpgid()的一个非显而易见的用途是允许作业控件shell将自身返回到其原始进程组(执行作业控件shell时生效的进程组)。作业控制shell在将控制权终止或暂停自身作为恢复其作业控制的方式之前将控制权返回给其父节点之前执行此操作#34; state&#34;回到父母的期望。

POSIX没有解释为什么作业控制shell会首先改变其进程组,但GNU C Library manual section on implementing job control填补了这个空白:

  

当一个正常执行作业控制的shell程序启动时,如果已从另一个已经在执行作业控制的shell中调用它,则必须小心。

     

以交互方式运行的子shell必须确保它已经被父shell置于前台,然后才能启用作业控制。

     

[...]

     

一旦子shell被其父shell置于前台,它就可以启用自己的作业控制。它通过调用setpgid将自己置于自己的进程组中,然后调用tcsetpgrp将此进程组置于前台来完成此操作。

然后,当然,如果子shell被挂起,它必须再次撤消(例如Bash有一个suspend内置来执行此操作。)

另请注意,作业控件shell 将自己建立为会话领导者,即使它不是任何子shell。任何负责建立控制终端的程序都会初始化会话;该程序通常是终端中运行的最外层shell的父级和exec标识。例如,xterm calls setsid在打开伪终端和分叉之后,exec之前 - 将在该终端窗口中运行的程序。