【问题标题】:Linux: Get the grandchild's pid C++Linux:获取孙子的 pid C++
【发布时间】:2018-07-26 16:20:41
【问题描述】:

我想创建一个函数,在其中传递一个结构,该结构将存储生成的进程的 pid。

bool spawnHost(string ttyNumber, DeviceData &deviceData)    
{
   pid_t processID = fork();
   pid_t hostProcessID = -1;
   if (processID == -1)
   {
       printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
       return false;
   }
   else if (!processID)
   {
       printf("PID:%d-> First child spawned. In Parent: %s", getpid(), processID);
       signal(SIGCHLD, SIG_IGN);
       hostProcessID = fork();
       if (hostProcessID == -1)
       {
          printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
          return false;
       }
       else if (!hostProcessID)
       {
          printf("PID:%d-> Starting %s at tty:%s", getpid(), hostAppPath.c_str(), ttyNumber.c_str());
          char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
          execvp(hostAppPath.c_str(), args);
       }
       else
       {
          printf("PID:%d-> First child spawned. In child: %s", getpid(), hostProcessID);            
          sleep(5);
          exit(0);
       }
   }
   else
   {
      int childStatus;
      waitpid(processID, &childStatus, 0);
      if (WIFEXITED(childStatus))
         printf("PID:%d has exited with exit code %d\n", processID, WEXITSTATUS(childStatus));

      deviceData.setProcessID(hostProcessID);
      return true;
    }
}

这里的要求是宿主进程(在第二个 fork 中产生)不能死亡,即使父进程死亡,宿主进程的 pid 应该存储在传递给 spawnHost() 的结构中功能。目前我无法获得 pid。我这个东东有问题吗?

我什至尝试了以下方法:

bool spawnHost(string ttyNumber, DeviceData deviceData)
{   
    string hostAppPath = EXE_PATH;

    signal(SIGCHLD, SIG_IGN);
    pid_t processID = fork();

    if (processID == -1)
    {
        printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
        return false;
    }
    else if (!processID)
    {
        signal(SIGCHLD, SIG_IGN);
        processID = fork();
        if (processID == -1)
        {
            printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
            return false;
        }
        else if (!processID)
        {
            if (setsid() < 0)
            {
                printf("PID:%d-> Unable to set new session ID. Error: %s", getpid(), strerror(errno));
                return false;
            }

            printf("PID:%d-> Starting %s at tty:%s", getpid(), hostAppPath.c_str(), ttyNumber.c_str());
            char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
            execvp(hostAppPath.c_str(), args);
        }
        else
        {
            deviceData.setProcessID(processID);
            exit(0);
        }
    }
    else
    {       
        return true;
    }   
    return true;
}

【问题讨论】:

  • 在 Linux 上,您可以在 /proc 中跟踪进程层次结构。
  • 您需要致电pipe2(fds,O_CLOEXEC),并使用它来传递信息,直到流程开始。我在这里编写了执行此操作的代码:github.com/o11c/python-vterm/blob/master/vterm/c-sources/…
  • @JesperJuhl 我试图获取第二个方法的进程树,因为新进程是在新会话中启动的,因此它嵌套在 init 进程中并且不属于主进程树
  • @o11c 非常感谢,它成功了。我能够得到孙子 pid。

标签: c++ linux fork pid


【解决方案1】:

感谢@o11c 我实现的答案是:

bool spawnHost(string ttyNumber, DeviceData &deviceData)
{
    int pipefd[2];      
    string hostAppPath = HOST_PATH_PREFIX + HOST_NAME + BUILD_DIR_STRING + HOST_NAME;

    if (pipe(pipefd) == -1)
    {
        printf("PID:%d-> IPC not possible as pipe failed");
        return false;
    }

    signal(SIGCHLD, SIG_IGN);
    pid_t processID = fork();

    if (processID == -1)
    {
        printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
        return false;
    }

    else if (!processID)
    {
        signal(SIGCHLD, SIG_IGN);
        processID = fork();
        if (processID == -1)
        {
            return false;
        }
        else if (!processID)
        {
            if (setsid() < 0)
            {
                printf("PID:%d-> Unable to set new session ID. Error: %s", getpid(), strerror(errno));
                return false;
            }
            char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
            execvp(hostAppPath.c_str(), args);
        }
        else
        {
            /// Write the host pid to the pipe
            close(pipefd[0]);
            write(pipefd[1], &processID, sizeof(processID));
            close(pipefd[1]);
            exit(0);
        }
    }
    else
    {
        close(pipefd[1]); /* Close unused write end */
        read(pipefd[0], &processID, sizeof(processID));
        close(pipefd[0]);
        wait(NULL);

        deviceData.setProcessID(processID);
        return true;
    }   
    return true;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 2021-02-10
    • 2021-08-08
    相关资源
    最近更新 更多