0

我正在尝试用 C 语言实现简单的 shell,但我很难实现作业控制。网上的一切似乎都足够复杂,我认为简单一点总是好的。所以让我问这个......在调用 fork() 之后,我可以只用 2 个函数和 pid 处理 Ctrl-Z 信号吗?

我想put_background(pid_t pid)在按下 Ctrl-Z 时调用一个函数 ex 并使用 pid = pid 使进程运行后台,最后put_foreground(pid_t pid)在我编写 fg 时调用另一个函数 ex 并且我希望 pid = pid 的进程再次进入前台。

那么,这可能吗?任何帮助表示赞赏.. 代码更多但是。

4

1 回答 1

1

我正在尝试用 C 语言实现简单的 shell,但我很难实现作业控制。网上的一切似乎都足够复杂,我认为简单一点总是好的。

所以让我问这个......在调用 fork() 之后,我可以只用 2 个函数和 pid 处理 Ctrl-Z 信号吗?

请注意,Ctrl-Z 主要对终端驱动程序有意义。它会导致将 aSIGTSTP发送到键入该字符的终端的前台进程组 - 即将该终端作为其控制终端并有权读取该终端的进程组。默认情况下,这会导致该组中的进程停止,但仅此而已。你不需要做任何事情来实现这一点。*

我想在按下 Ctrl-Z 时调用一个函数 ex put_background(pid_t pid) 并使用 pid = pid 进行进程以运行后台,最后在我编写 fg 时调用另一个函数 ex put_foreground(pid_t pid) 并且我想要使用 pid 的进程= pid 再次进入前台。

根据定义和设计,在任何特定时间最多有一个进程组可以控制给定的终端。因此,要将前台作业移至后台,您只需将另一个作业移至前台即可。这可以是外壳本身,也可以是它控制的其他工作。库tcsetpgrp()函数实现了这一点。除非它是 shell 本身,否则您还需要SIGCONT向该进程组发送 a 以防它被停止。

您还需要一种机制来恢复已停止的后台作业,但这很简单:只需向该进程组发送一个SIGCONT.

那么,这可能吗?任何帮助表示赞赏.. 代码更多但是。

可以肯定的是,您可以编写一个函数来将作业移至前台并恢复它,以及一个用于恢复后台作业的函数。这些函数需要的关于它们操作的作业的唯一信息是它们的进程组 ID(与它们的初始进程的进程 ID 相同)。

但是您还需要维护一些当前活动作业的簿记,并且您需要注意开始新作业,并且您需要监控当前作业 - 尤其是前台作业 - 以便能够协调所有适当的过渡。

GLIBC 手册有一整章是关于作业控制的,包括专门关于实现作业控制外壳的实质性部分。即使您不是为基于 GLIBC 的系统编写代码,这也可能对您有用。所需的实际代码并不是那么复杂,但要正确使用它需要对相当广泛的概念有很好的理解。


*但是您确实需要确保您的 shell 将它启动的命令放入与其自己不同的进程组中,否则 Ctrl-Z 也会停止它。

于 2018-10-20T21:11:45.647 回答