将进程发送到后台并返回控制权给我的shell

7

我正在为我的CS课程编写一个shell,其中项目的一部分涉及如果用户传入'&'字符,则在后台运行进程。

如果在前台运行进程,我只需要execvp该进程并将其保留在终端控制下,因为它是在前台。但是,如果它是后台进程,则必须在启动进程的执行后将控制权返回到我的主shell。我知道系统调用tcsetpgrp(pid_t)会将传递的进程作为参数放置在前台,但我不太明白如何使用它。

如果是后台进程,我应该在execvp之后调用tcsetpgrp吗?如果是这样,我可以通过调用getpid来获取我的shell的pid吗?


让我们试试这个。在您喜欢的终端中启动两个会话。在第一个会话中运行一个命令,比如说cat,并将其放在fg中。切换到另一个会话,使用ps查找cat的pid。使用kill发送SIGSTOP信号给它。观察发生了什么并分享您的发现。 - tuxuday
3个回答

10

tcsetpgrp()函数作用于进程组,而非单个进程。想要实现的功能是:

  1. 在创建新的管道时,调用setpgid()将管道中所有成员放入新的进程组(使用管道中第一个进程的PID作为PGID)。 (管道是由您的shell启动的一系列进程,当它看到类似ls | grep foo | wc -l这样的请求时 - 最简单的管道只有一个进程)。通常情况下,您会在调用exec()之前从管道中的第一个进程中调用 setpgid(0, 0)

  2. 使用tcsetpgrp()来管理前台进程组。如果将进程组从前台移动到后台,则将shell自己的进程组设置为前台进程组 - 您可以使用getpgid(0)在shell中获取这个值。

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

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


-1
如果您的shell使用&将进程放到后台运行,那么$! shell变量将包含子进程的PID。然后您可以向该进程发送信号,或使用wait $!等待其完成。

-2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接