为什么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冲突。