【问题标题】:C: Exec/fork > Defunct processesC: Exec/fork > 已失效的进程
【发布时间】:2011-10-06 18:59:55
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: c exec fork defunct


    【解决方案1】:

    首先你的第二个问题!

    您的孩子会停留在“僵尸”模式,因为内核认为您可能仍想从他们那里获取返回值..

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

    signal(SIGCHLD, SIG_IGN);
    

    第一个问题取决于你的实现..

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

    【讨论】:

    • 来自“Linux 编程接口”的有趣引述:“请注意,即使 SIGCHLD 的默认配置将被忽略,但将配置显式设置为 SIG_IGN 会导致此处描述的不同行为。在这方面, SIGCHLD 在信号中被唯一对待。”
    【解决方案2】:

    您的子进程正在被杀死。 Defunct processes也叫zombie processes;僵尸死了!僵尸进程只是进程表中的一个条目,它没有任何代码或内存。

    当一个进程死亡时(通过调用_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);
    

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

    ./spawnbot >logging.txt 2>&1
    

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

    nohup ./spawnbot >logging.txt 2>&1 &
    disown
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      • 2017-02-25
      • 1970-01-01
      相关资源
      最近更新 更多