为什么fork()在setsid()之前

为什么fork()之前setsid()守护进程?

基本上,如果我想从控制terminal中分离一个进程,并使其成为一个进程组的领导:我使用setsid()

这样做而不分叉之前不起作用。

为什么?

首先:setsid()将使你的进程成为一个进程组的领导者,但它也将使你成为一个新的会话的领导者。 如果你只是想获得你自己的进程组,然后使用setpgid(0,0)。

现在为了理解为什么setsid()返回EPERM的真实原因,如果你已经是进程组长或者会话负责人,你必须明白进程组和会话ID是从创build进程的进程ID初始化的对于会议领导者pid == sid和进程组领导者pid == pgid)。 另外进程组不能在会话之间移动。

这意味着如果你是一个过程组的领导者,并且创build一个新的会话将被允许,那么sid和pgid将被设置到你的pid中,而把旧的过程组中的其他进程置于一个奇怪的状态:他们的过程组领导忽然是在不同的会议,然后他们自己可能会。 这是不允许的,因此核心EPERM。

现在,如果fork()既不是会话也不是进程组领导,因此将你的sid和pgid设置为你的pid是安全的,因为在这个组中没有其他进程。

所以呢,想一想,这一切都是有道理的。

需要fork()并让child调用setsid()来确保调用setsid()的进程不是一个进程组头( setsid()想要使调用进程成为进程的进程组头组,所以在这种情况下失败)。

man 2 setsid ,你会得到以下描述:

如果调用进程不是进程组头,则setsid()将创build一个新的会话。 调用进程是新进程的负责人,新进程组的进程组负责人,没有控制terminal。 调用进程的进程组ID和会话ID被设置为调用进程的PID。 调用过程将是这个新的过程组和这个新的过程中唯一的过程。

如果一个进程组的领导被允许调用setsid() ,创build一个新的会话和一个新的进程组(具有相同的进程组ID),则会导致进程组ID冲突。