请告诉我进程组ID和jobid之间的区别。jobid 是 shell 程序的内置函数还是与内核有关?它们各自的用途是什么?当一个进程在后台运行时,是只设置了jobid还是设置了pgid?setpgid() 函数的用途是什么?
当一个进程在后台运行时,是否还涉及内核或外壳程序是否处理哪个是后台或前台?
好问题。作业 id 主要只是一个 shell 结构。内核中以涉及作业控制的信号的形式提供支持,以及内核确切知道将作业控制信号发送到哪些进程的方式。
严格来说,你的第一个问题的答案是,job id 纯粹是一个 shell 创建。它的存在是因为管道(或很少是另一个外壳分组结构)可能包含多个应作为一个单元进行控制的进程。
为了回答您的最后一个问题,shell 通过先执行 afork(2)
然后执行a 来启动所有进程execve(2)
。唯一的区别&
是外壳不执行wait(2)
(或相关变体),因此程序可以“在后台”继续。在 Unix 中,前台和后台实际上几乎没有区别。
进程组是由 shell 定义的关联,以便内核知道处理一组不同“后台”进程的单个“前台”进程。这很重要,以便后台进程在决定突然从终端读取时生成信号。(这样的终端可能连接到标准输入。)这将导致“工作”产生一个信号,shell 将提示用户做某事。
尝试(sleep 5; read x)&
并在 6 秒后键入 return 或其他内容,以便 shell 唤醒。这时候你会看到类似...
[1]+ 停止(睡眠 5;读取 x)
...然后您键入fg
以将其拉到前台。
最初,Unix 有管道,它也有&
,但是没有办法在前台和后台之间移动命令或管道,也没有办法帮助突然决定读取标准输入的后台进程。
Bill Joy 和其他人在 BSD 和 csh(1) 的早期版本中添加了作业控制及其内核支持。这些是由商业 Unix 逐行提取的,并被克隆用于类似工作的 Linux 内核。
关于进程组的问题ps(1)
......为了支持shell中的作业控制,内核进程状态包括进程组ID和会话ID。进程组和作业是一回事,但作业号只是外壳组成的句柄。如果会话 ID 与 pid 相同,则进程是会话领导者,如果 pgid 与 pid 相同,则进程是进程组领导者。+
我相信那些ps(1)
印刷品正在发生一些更微妙的事情。每个终端都知道它的前台进程组是什么,所以我相信如果 pid == pgid && (pgid 是其控制终端的前台 pg),一个进程会得到一个 +。
In summary, the kernel keeps several items of state: pid, pgid, sid, and a process may have a controlling terminal and a terminal may have a foreground pgid. These credentials are mostly intended to support job control but are also used to revoke access to a terminal when a user logs out.