7

我正在为我的 CS 类编写一个 shell,如果用户传入了“&”字符,则该项目的一部分涉及在后台运行一个进程。

如果一个进程在前台运行,我只是execvp该进程,它仍然控制着终端,因为它在前台。但是,如果它是后台进程,我必须在开始执行该进程后将控制权返回给我的主 shell。我知道系统调用tcsetpgrp(pid_t)将作为参数传入的进程放在前台,但我不太明白如何使用它。

如果它是后台进程,tcsetpgrp我应该打电话吗?execvp如果是这样,我可以通过调用来获取我的 shell 的 pidgetpid吗?

4

3 回答 3

10

tcsetpgrp()适用于流程组,而不是单个流程。你想要做的是:

  1. 创建新管道时,调用setpgid()将管道的所有成员放入一个新的进程组中(以管道中第一个进程的 PID 作为 PGID)。(管道是您的外壳在看到类似请求时启动的一系列进程ls | grep foo | wc -l- 最简单的管道中只有一个进程)。通常你会setpgid(0, 0)从管道中的第一个进程调用,然后再调用exec().

  2. 用于tcsetpgrp()管理哪个进程组在前台。如果你将一个进程组从前台移动到后台,你可以将 shell 自己的进程组设置为前台进程组——你可以getpgid(0)在 shell 中得到它。

  3. 当 shell 在后台时,它应该使用阻塞waitpid()调用来等待子进程退出而不是显示提示。一旦前台管道中的每个进程都退出,它应该再次将自己放回前台(并显示提示)。

  4. 当 shell 处于前台时,它应该在您显示提示之前调用和waitpid()标志来检查子进程的状态 - 这将在它们停止或退出时通知您,并让您通知用户。WNOHANGWUNTRACED

于 2012-05-28T04:51:58.150 回答
-1

如果您的 shell 启动一个进程&用于后台运行,$!shell 变量将包含子进程的 PID。然后,您可以向该进程发送信号,或用于wait $!等待它完成。

于 2012-05-28T06:23:47.967 回答
-2

你应该看看fork来创建子进程。然后,exec在孩子中使用以运行所需的命令。

于 2012-05-28T04:27:22.250 回答