【问题标题】:Implementing shell-like job control in C在 C 中实现类似 shell 的作业控制
【发布时间】:2018-10-20 19:20:47
【问题描述】:

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

我想调用一个函数,例如put_background(pid_t pid) 当我按下 Ctrl-Z 并使用 pid = pid 进行进程以运行后台并最终调用另一个函数 e.x. put_foreground(pid_t pid) 当我写 fg 并且我希望 pid = pid 的进程再次进入前台时。

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

【问题讨论】:

  • Ctrl-Z 不在后台运行程序,它暂停它(通过发送SIGTSTP)。
  • 这不是重点,我可以随心所欲地处理信号,但是我可以只用 pid 在前景和背景之间切换吗?
  • 我们是否假设您在谈论 POSIX 环境?因为标准 C 本身没有任何作业的概念,更不用说作业控制、分叉等。这些东西在不同类型的环境中的工作方式不同,如果有的话。
  • @CharlesDuffy,我对前台和后台的描述完全不同:前台作业是具有控制终端并且当前有权读取它的作业。虽然它的父级很可能是一个 shell 并且在上面是 waiting,但这不是基本特征。
  • 我必须同意——在这一点上,curiousthing.org/sigttin-sigttou-deep-dive-linux 可能是 OP 的有用资源。

标签: c pid job-control


【解决方案1】:

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

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

请注意,Ctrl-Z 主要对终端驱动程序有意义。它会导致SIGTSTP 被发送到输入该字符的终端的前台进程组——即将该终端作为其控制终端并有权读取该终端的进程组。默认情况下,这会导致该组中的进程停止,但仅此而已。您无需执行任何操作即可实现这一目标。*

我想调用一个函数,例如put_background(pid_t pid) 当我点击 Ctrl-Z 并使用 pid = pid 创建进程以运行后台,最后 调用另一个函数例如当我写 fg 时 put_foreground(pid_t pid) 我希望 pid = pid 的进程再次进入前台。

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

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

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

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

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

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


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

【讨论】:

  • 你确实让一些事情变得更加清晰......非常感谢,我会检查 GLIBC 手册,我认为这就是我想要的
猜你喜欢
  • 2015-08-03
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 2019-03-23
相关资源
最近更新 更多