简体   繁体   English

为什么在 GNU 中我们从 shell 中 tcsetpgrp 而它是一个后台进程?

[英]Why in GNU do we tcsetpgrp from a shell while it is a background process?

I've been studying this link to finish my shell assignment: http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs and it's been particularly helpful.我一直在研究这个链接来完成我的 shell 作业: http ://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs 它特别有用。 My confusion is that, to give the shell control of the stdin file descriptor again, I need to call tcsetpgrp from the shell after the child is terminated.我的困惑是,为了再次让 stdin 文件描述符的 shell 控制,我需要在 child 终止后从 shell 调用tcsetpgrp

How do I get tcsetpgrp() to work in C? 如何让 tcsetpgrp() 在 C 中工作?

I've searched different Stack Overflow questions, but none properly tell me why GNU promotes this approach.我搜索了不同的 Stack Overflow 问题,但没有一个正确地告诉我为什么 GNU 提倡这种方法。 Because the shell currently is in the "background", tcsetpgrp() will send SIGTTOU to my process group.因为 shell 当前处于“后台”, tcsetpgrp()会将 SIGTTOU 发送到我的进程组。 The current solution is to ignore it before calling the method and maybe reset it to default afterwards.当前的解决方案是在调用该方法之前忽略它,然后可能将其重置为默认值。 What should I do?我应该怎么办?

EDIT: I would like to note that the child is first set in another process group before the shell passes control of stdin to it with tcsetpgrp() .编辑:我想指出的是,在 shell 使用tcsetpgrp()将 stdin 的控制权传递给它之前,该子进程首先被设置在另一个进程组中。 Once the child dies, the shell calls tcsetpgrp() to reclaim stdin.一旦孩子死亡,shell 调用tcsetpgrp()来回收标准输入。 GNU suggests this as a possible implementation, but says it uses a slightly different implementation for simplicity here . GNU 建议将此作为一种可能的实现方式,但表示为了简单起见,它在这里使用了一种略有不同的实现方式。

If tcsetpgrp() is called by a member of a background process group in its session, and the calling process is not blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to all members of this background process group.如果tcsetpgrp()在其会话中被后台进程组的成员调用,并且调用进程未阻塞或忽略 SIGTTOU,则 SIGTTOU 信号将发送到该后台进程组的所有成员。

I'm also towards the end of implementing a shell program, and can take a stab at this question:我也快要完成一个 shell 程序了,可以试一试这个问题:

TL;DR: even though the shell will be a background process at that point, it needs to reclaim the terminal foreground for itself once the most recent foreground process group exits; TL;DR:即使此时 shell 将是后台进程,一旦最近的前台进程组退出,它也需要为自己回收终端前台; otherwise the terminal will hang and no process will consume the user's input.否则终端会挂起,没有进程会消耗用户的输入。

Here's what the session looks like when a shell launches a job from a line of command:以下是 shell 从命令行启动作业时会话的样子:

  1. before the child processes call execve(), they are assigned into a process group, so that it's simpler to manage them as a job;在子进程调用execve()之前,它们被分配到一个进程组中,这样更容易将它们作为一个作业来管理;
  2. now that the shell and the child processes are in different process group, and that the terminal can only serve one process group at a time, the shell has to donate the terminal foreground to this child process group, so that the child job could read inputs and receive signals directly from the user;现在 shell 和子进程在不同的进程组中,并且终端一次只能为一个进程组服务,shell 必须将终端前台捐赠给这个子进程组,以便子作业可以读取输入并直接从用户那里接收信号;
  3. after the foreground donation, the shell becomes a background process, but since there's no point in running the shell in the background (its main function is to read/write to the terminal and launch jobs), it should not proceed until it reclaims the foreground;在前台捐赠之后,shell 变成了后台进程,但是由于在后台运行 shell 没有意义(它的主要功能是读/写终端和启动作业),它不应该继续,直到它回收前台;
  4. another reason why the shell must immediately reclaim the foreground after the exit of the most recent child foreground process group, is that there will be no running process consuming the terminal input/signal between the time a) when the child foreground process group exit, and b) when the shell reclaims the foreground. shell 在最近的子前台进程组退出后必须立即回收前台的另一个原因是,在子前台进程组退出的时间 a) 和b) 当 shell 回收前台时。 The terminal will essentially hang and become unresponsive;终端基本上会挂起并变得无响应;
  5. as for why the shell must reclaim the foreground itself, it's because the child processes will be calling execve() and loading entirely new process images.至于为什么 shell 必须自己回收前台,这是因为子进程将调用 execve() 并加载全新的进程映像。 It is extremely difficult to enforce and advocate for a contract where every child process in the foreground returns the foreground back to the shell process;执行和提倡前台中的每个子进程都将前台返回到 shell 进程的合同是极其困难的;
  6. lastly, since tcsetpgrp() sends the caller background process a SIGTTOU, the shell must register an ignorer handler for SIGTTOU, at least during the time it's reclaiming the terminal foreground;最后,由于 tcsetpgrp() 向调用者后台进程发送一个 SIGTTOU,shell 必须为 SIGTTOU 注册一个忽略处理程序,至少在它回收终端前台期间;

The GNU C Library manual also has another section (28.5.4 Foreground and Background) that briefly explains why the shell must reclaim the terminal forg GNU C 库手册还有另一节(28.5.4 前景和背景)简要解释了为什么 shell 必须回收终端 forg

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM