14

我想使用 fork > exec 过程创建很多子进程。许多进程都很快结束(不到两分钟,有些甚至更早)。

我的第一个问题是,我将生成过程置于后台

./spawnbot > logging.txt
[CTRL+Z]
bg 1
disown

到目前为止,一切都很好。现在我再也看不到 spawnbot 的任何消息,它们直接进入 logging.txt。但是,每当创建一个新孩子时,我都会再次在我的控制台中看到有关该孩子的所有信息。我现在想用它自己的管道启动每个孩子 - 有没有更好的方法不让孩子在整个过程中发布他们的输出消息安慰?我应该将它重定向到 /dev/null 还是使用 C 中的某些标志来完成?

其次,并不是所有的孩子都真的被杀了。我的 ps -ef 中有很多进程。我能做些什么呢?我该怎么做

4

2 回答 2

22

首先你的第二个问题!

你的孩子停留在“僵尸”模式,因为内核认为你可能仍然想从他们那里检索返回值。

如果您不打算从子进程中获取返回值,则应将父进程中的 SIGCHLD 信号处理程序设置为 SIG_IGN 以让内核自动获取您的子进程。

signal(SIGCHLD, SIG_IGN);

第一个问题取决于您的实施..

但一般来说,在你 fork() 之后,你应该使用close()关闭 0 和 1 的旧文件描述符,然后使用dup2()将它们设置为你想要的值。现在没有时间举例,但希望这能推动你正确的方向。。

于 2011-07-16T16:31:22.933 回答
18

您的子进程正在被杀死。已失效的进程也称为僵尸进程;僵尸死了!僵尸进程只不过是进程表中的一个条目,它没有任何代码或内存。

当一个进程死亡(通过调用_exit,或被信号杀死)时,它必须由其父进程收割。除了进程表中的条目之外,进程使用的所有资源都消失了。家长必须调用waitwaitpid。一旦父进程收到子进程死亡的通知,并且有机会读取子进程的退出状态,进程表中子进程的条目也会消失:僵尸被收割。

如果您不想收到孩子死亡的通知,请忽略该SIGCHLD信号;这告诉内核你对知道你孩子的命运不感兴趣,僵尸将被自动收割。

signal(SIGCHLD, SIG_IGN)

如果您只想在特定情况下收到您孩子死亡的通知,请sigaction举旗SA_NOCLDWAIT打电话。当一个孩子死亡时,如果父母正在执行其中一个wait家族的功能,它会被告知孩子的死亡,并被告知退出状态;否则孩子的退出状态将被丢弃。

struct sigaction sa;
sa.sa_handler = &my_sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, NULL);

关于输出,您的孩子写到与父母相同的地方,除非您明确重定向他们(使用closeand open、 ordup或许多其他可能性)。您的孩子可能正在将诊断消息打印到标准错误(毕竟这就是它的用途)。

./spawnbot >logging.txt 2>&1

此外,由于您似乎想将子代与终端分离,因此您可能希望确保在您终止终端时他们不会收到SIGHUP。所以使用nohup

nohup ./spawnbot >logging.txt 2>&1 &
disown
于 2011-07-16T17:20:00.463 回答