在C语言的基本Shell程序中,如何退出与父进程关联的所有进程?

在C语言的基本Shell程序中,如何退出与父进程关联的所有进程?,c,shell,fork,exit,child-process,C,Shell,Fork,Exit,Child Process,我正在为大学作业编写一个基本的shell程序,我需要测试用户何时输入字符串“exit”。发生这种情况时,程序应该退出 我可以成功地对此进行测试,但如果我已经分叉了处理程序中的strerror的新进程,那么无论当前有多少活动进程正在运行,我都必须继续进入exit 在这种情况下,是否有办法退出与程序相关的所有进程 干杯 正如评论中所说,您不应该在后台生成交互式进程(至少您的shell和命令将如何处理唯一的stdin?) 作为一个shell,您还应该跟踪所有生成的进程(在后台),以便能够捕获它们的返回

我正在为大学作业编写一个基本的shell程序,我需要测试用户何时输入字符串“exit”。发生这种情况时,程序应该退出

我可以成功地对此进行测试,但如果我已经分叉了处理程序中的strerror的新进程,那么无论当前有多少活动进程正在运行,我都必须继续进入exit

在这种情况下,是否有办法退出与程序相关的所有进程


干杯

正如评论中所说,您不应该在后台生成交互式进程(至少您的shell和命令将如何处理唯一的stdin?)

作为一个shell,您还应该跟踪所有生成的进程(在后台),以便能够捕获它们的返回代码,就像在sh/bash中所做的那样(至少)。例如,在bash中:

> sleep 1 &
[1] 8215
>
(1 sec later)
[1]+  Terminated      sleep 1
因此,如果您有现有子级的列表,您可以向所有子级发送SIGINT/SIGKILL

不管怎样,如果你真的想确保杀死所有人,你应该使用过程组(PG)杀戮。使用PID=0的
kill()
函数将kill信号发送到与您相同的进程组中的所有进程。 因此,您可以通过设置一个新的进程组来启动shell(确保不会杀死其他进程组),并且这个PG将由您的孩子继承(当然,如果孩子设置了一个新的PG,那么这个PG将被继承)

这看起来像:

// at the begining of your main code
// try to get a new process group for me
x = setpgid(0,0);
if (x == -1) {
  perror("setpgid");
  exit(1);
}
(…)
// here you're about to exit from main, just kill
// all members of your group
kill(0, SIGINT);  // send an INT signal
kill(0, SIGKILL); // paranoid: if a child catch INT it will get a KILL

// now you can exit, but you're probably dead 'cause you
// also receive the SIGINT. If you want to survive you have to
// catch SIGINT, but you will not catch KILL whatever

如果您需要在杀戮中幸存下来,您可以使用
signal()
或更好的
sigaction()
捕捉信号,这样您就不会被杀戮,从而能够在退出前执行其他操作。

为什么这些进程等待输入?他们不应该离开吗?如果你有所有直系子女的记录,你可以让你的父母给他们发送死亡威胁(SIGHUP,SIGTERM)。但这不是必须的。除非shell是交互式的,否则它应该在出现错误时退出,或者到达脚本的末尾。是的,即使是真正的shell,在后台生成与stdin交互的命令也不是一个好主意……正如@JonathanLeffler所说,无论您的shell应该跟踪后台进程的PID,至少要获取它们的返回代码(例如BASH所做的)。如果您的shell不支持作业控制(这很可能是因为您没有提到它),您肯定不想/不需要这样做,这强烈暗示您做错了什么。当shell分叉以执行用户键入的命令时,它应该等待该进程终止,然后再接受进一步的输入。这反过来意味着在上一个命令终止之前,用户无法键入
退出
。所以你根本不必担心这个。当然,命令可能已经分叉并立即退出,但对于大学作业,我不会担心这一点。
setpgid(2)
返回
int
,不需要在
if
中执行强制转换。此外,问题的措辞方式似乎是多个进程同时尝试读取
stdin
(这可能是不可取的),因此,在主shell程序中执行此操作不一定会修复它,除非您足够幸运,能够将准确的输入行传递到shell进程。@FilipeGonçalves:是的,您是对的。与
getpgid()
混淆。我更正了这篇文章。注意:“多个进程同时尝试从stdin读取数据”,因为这是一个无稽之谈(正如你所说),我假设一个连贯的代码:)