【问题标题】:Forking and running dhclient (with params -nw -w) in exec creates a defunct process and a daemon process在 exec 中分叉和运行 dhclient(使用参数 -nw -w)会创建一个失效进程和一个守护进程
【发布时间】:2019-05-13 13:45:21
【问题描述】:

当我从父进程分叉然后执行带有参数的 dhclient 进程时,我看到了一个僵尸进程和 dhclient 进程

这是输出

root     31298  0.0  0.0      0     0 pts/2    Z    09:22   0:00 [dhclientForData] <defunct>
root     31410  0.0  0.0  24260  9108 ?        Ss   09:23   0:00 -nw -w -sf etc/dhclient-script -pf /var/run/dhclient-vEth0.pid -lf /var/lib/dhcp/dhclient-vEth0.leases -cf /etc/sysconfig/dhclient.conf vEth0

我已在父进程中将 linux 系统 dhclient 重命名为 dhclientForData。请注意上面输出中的第二行,我没有看到 dhclient 进程名称只是参数我不知道为什么,有人吗?

我的代码

func_parent()
{
       pid_t child = 0;
        child = fork();
        if (child < 0)
        {   
            return 0;
        }
        if (child == 0)
        {   
            wanIntfDhclientHandlerProcessChildAdd ();
        }
        shmWlanTunMonitrConfig->childProcs[index].procId = child;
        sleep(1);
    }

    uint8_t wanIntfDhclientHandlerProcessChildAdd ()
    {
        pid_t mypid = getpid();
        uint8_t idx = gindex;
        //for (; idx < MAX_WAN_PORTS; idx++)
        {   
            if (!shmWlanTunMonitrConfig->childProcs[idx].isRunning && shmWlanTunMonitrConfig->childProcs[idx].cmdIdx != 0xFF)
            {   
                shmWlanTunMonitrConfig->childProcs[idx].isRunning = 1;

                char *const argV[] = {commands[idx].cmd[0],
                commands[idx].cmd[1],
                commands[idx].cmd[2],
                commands[idx].cmd[3],
                commands[idx].cmd[4],
                commands[idx].cmd[5],
                commands[idx].cmd[6],
                commands[idx].cmd[7],
                commands[idx].cmd[8],
                commands[idx].cmd[9],
                commands[idx].cmd[10],
                NULL};
                int ret = execvp(WAN_EXECUTABLE, argV);
    }
    }
    }

我已注册到 sigchld 并将在该进程上等待pid。我有多个进程正在运行

pid_t pid = waitpid(shmWlanTunMonitrConfig->childProcs[index].procId, &status, WNOHANG);

如果不再需要该作业,我只是从我的父进程中删除该进程。

char cmd[512] = {0};
sprintf(cmd, "for KILLPID in `ps ax | grep \'/var/run/dhclient\' | grep \'%s\' | awk \' { print $1;}\'`; do kill -9 $KILLPID; done", portIntfAr[index].intfName);
system (cmd);

谁能指出我做错了什么。

赛义德

【问题讨论】:

  • 在询问有关运行时问题的问题时,就像这个问题一样。请发布minimal reproducible example,以便我们重新创建问题,以便我们可以帮助您调试,它
  • exec*() 函数不会返回,除非在启动子进程时发生错误。所以返回的值可以/应该被完全忽略,并在调用之后使用perror( "execlp failed" ); exit( EXIT_FAILURE );
  • OT:关于if (child &lt; 0) { return 0;,当发生错误时,接下来的两条语句应该是:perror( "fork failed" ); exit( EXIT_FAILURE ); 注意返回值 0(通常)表示成功,但是。实际上,应用程序失败了

标签: c signals fork exec


【解决方案1】:

僵尸进程31298 只要父进程还没有等待它就存在,因此您的进程表或waitpid 调用可能有问题。 我无法检查,因为您的代码不完整。

除了等待特定的 PID,您还可以等待任何子进程或进程组,然后从生成的 siginfo_t 结构中找出哪个进程刚刚报告了其状态更改。

我不知道你用哪个字符串赋值

char *const argV[] = {commands[idx].cmd[0],
/* ... */

argv[0]应该是程序的文件名,即和WAN_EXECUTABLE一样

【讨论】:

  • 谢谢博多,这有帮助。但我有一个后续问题。由于 dhclient 以守护程序模式运行。它与父级分离,这意味着我不再控制它,因为它有自己的进程组。有没有办法修复它并始终控制它?
  • @SyedTowkhir 您到底想对dhclient 进程做什么?为什么将其实现为 C 程序?我认为一个shell脚本就足够了。如果您不希望 dhclient 作为守护进程运行,您可以省略 -nw 选项并添加 -d(强制 dhclient 作为前台进程运行。)如果您的 dhclient 支持此功能。 (阅读man dhclient)您指示dhclient 将其PID 写入文件。您可以使用文件中的 PID 来杀死它,而不是解析 ps 的输出。 kill -9 只有在没有其他方法的情况下才应该使用。被终止的程序无法保存状态或清理。
  • 我同意这是一种粗鲁的方式。我将修改为使用 pid 文件。
猜你喜欢
  • 2011-06-07
  • 1970-01-01
  • 2015-02-25
  • 2014-04-12
  • 2014-07-03
  • 1970-01-01
  • 2010-12-16
  • 2016-01-07
  • 1970-01-01
相关资源
最近更新 更多