c++fork,不需要等待,即可解压execl

c++ fork, without wait, defuncts execl

本文关键字:execl 不需要 等待 c++fork      更新时间:2023-10-16

在c++中,想要派生一个不会挂起其父进程的进程——其父进程是一个守护进程,必须保持运行。如果我在forked进程上等待(),forked execl不会取消资助-但是-它也会挂起应用程序-不等待修复应用程序挂起-但是命令变为取消资助。

if((pid = fork()) < 0)
    perror("Error with Fork()");
else if(pid > 0) { 
    //wait here will hang the execl in the parent
    //dont wait will defunt the execl command 
    //---- wait(&pid);
    return "";
} else {
    struct rlimit       rl;
    int                 i;
    if (rl.rlim_max == RLIM_INFINITY)
        rl.rlim_max = 1024;
    for (i = 0; (unsigned) i < rl.rlim_max; i++)
        close(i);
    if(execl("/bin/bash", "/bin/bash", "-c", "whoami", (char*) 0) < 0) perror("execl()");
    exit(0);
}

在execl的命令不会失效的情况下,我如何在没有等待(&pid)的情况下分叉execl?

更新通过在分叉之前添加以下内容修复

signal(SIGCHLD, SIG_IGN);

仍在利用我有限的技能,在公认答案的基础上找到一个更兼容的解决方案。谢谢

默认情况下,wait和朋友会等待进程退出,然后收获它。如果没有子进程退出,您可以用WNOHANG调用waitpid以立即返回。

失效的/"僵尸"进程将一直存在,直到你在它上wait。因此,如果你在后台运行它,你必须安排最终通过以下几种方式获得它:

  • 常规试用waitpidWNOHANGint pid = waitpid(-1, &status, WNOHANG)
  • SIGCHLD安装一个信号处理程序,以便在其退出时得到通知

此外,在POSIX.1-2001下,可以使用sigactionSIGCHLD上设置SA_NOCLDWAIT。或者将其操作设置为SIG_IGN。较旧的系统(包括Linux 2.4.x,但不包括2.6.x或3.x)不支持此功能。

检查您的系统手册页,或者在"单一Unix规范"中选择等待。Single Unix Spec还提供了一些有用的代码示例。SA_NOCLDWAIT记录在sigaction中。

我认为信号处理程序将是所示的最佳方式。我想指出另一种处理方法:分叉两次,让孩子退出,而孙子会调用execl。然后,init进程将清理已失效的进程。

正如注释中所说,双叉将进程从失效状态保存下来。

创建守护程序时执行双分叉的原因是什么?

EX1:当客户端不退出时,不等待

#include <spawn.h>
extern char** environ; //posix_spawn using environ that declare in glibc-2.xx/posix/environ.c
void main()
{
    pid_t   spawnid;
    char    param[64] = {0};
    char*   args[] = {"/usr/drive_server", param, NULL};
    posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args, 
    environ);
    getchar();
}

EX2:当客户端退出时,等待子进程分离

#include <spawn.h>
extern char** environ;
void main()
{
    pid_t   spawnid;
    char    param[64] = {0};
    pid_t   sessionid;
    char*   args[] = {"/usr/drive_server", param, NULL};
    
    posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args, environ);
    
    sessionid = 0;
    while( sessionid != spawnid )
    {
        sessionid = getsid(spawnid);
        printf("sessionid id %dn", sessionid);
        usleep(200000);
    }
}
    //subprocess file
    void main()
    {
        setsid(); //detach
        getchar();
    }

EX3:当系统有setsid命令时,不等待

#include <spawn.h>
extern char** environ;
void main()
{
    pid_t   id_spawn;
    char*   args[] = {"/usr/bin/setsid", "/volume1/drive_server", serviceName8, NULL};
    posix_spawn(&id_spawn, "/usr/bin/setsid", NULL, NULL, args, environ);
    printf("drive_server* spawn id %dn", id_spawn);
}

有两种源代码可以参考

  1. util-linux-2.xx.x/sys utils/setsid.c
  2. busybox-1.xx.x/util-linux/setsid.c