c++ - 从 popen 获取 PID

标签 c++ c popen pid

我有一个程序使用 popen() 来打开和读取 shell 命令的输出。问题是,据我所知,没有简单的方法来获取正在运行的进程的 PID,因此,如果它被卡住,你不能杀死它。所以问题是,如何从使用 popen 打开的进程中检索 PID?

最佳答案

我想出的解决方案(和普遍共识)是创建一个新的 popen 函数,它允许我检索 PID。由于我无法在 SO 上找到一个简单的示例,因此我想发布我的实现,希望它能帮助其他人。欢迎提供反馈和替代解决方案。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <string>
#include <sstream>

using namespace std;

#define READ   0
#define WRITE  1
FILE * popen2(string command, string type, int & pid)
{
    pid_t child_pid;
    int fd[2];
    pipe(fd);

    if((child_pid = fork()) == -1)
    {
        perror("fork");
        exit(1);
    }

    /* child process */
    if (child_pid == 0)
    {
        if (type == "r")
        {
            close(fd[READ]);    //Close the READ end of the pipe since the child's fd is write-only
            dup2(fd[WRITE], 1); //Redirect stdout to pipe
        }
        else
        {
            close(fd[WRITE]);    //Close the WRITE end of the pipe since the child's fd is read-only
            dup2(fd[READ], 0);   //Redirect stdin to pipe
        }

        setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
        execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL);
        exit(0);
    }
    else
    {
        if (type == "r")
        {
            close(fd[WRITE]); //Close the WRITE end of the pipe since parent's fd is read-only
        }
        else
        {
            close(fd[READ]); //Close the READ end of the pipe since parent's fd is write-only
        }
    }

    pid = child_pid;

    if (type == "r")
    {
        return fdopen(fd[READ], "r");
    }

    return fdopen(fd[WRITE], "w");
}

int pclose2(FILE * fp, pid_t pid)
{
    int stat;

    fclose(fp);
    while (waitpid(pid, &stat, 0) == -1)
    {
        if (errno != EINTR)
        {
            stat = -1;
            break;
        }
    }

    return stat;
}

int main()
{
    int pid;
    string command = "ping 8.8.8.8"; 
    FILE * fp = popen2(command, "r", pid);
    char command_out[100] = {0};
    stringstream output;

    //Using read() so that I have the option of using select() if I want non-blocking flow
    while (read(fileno(fp), command_out, sizeof(command_out)-1) != 0)
    {
        output << string(command_out);
        kill(-pid, 9);
        memset(&command_out, 0, sizeof(command_out));
    }

    string token;
    while (getline(output, token, '\n'))
        printf("OUT: %s\n", token.c_str());

    pclose2(fp, pid);

    return 0;
}

关于c++ - 从 popen 获取 PID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26852198/

相关文章:

c++ - 如何在c++的末尾获取具有特定数字的声明变量

c++ - 将 Uint8(浮点 AUDIO_F32)转换为 int16_t(16 位 PCM)

C语言将char类型 '0' -'9'转换成int类型打印到stdout

c - STM32F4探索和CAN编程

python - 在运行时拦截子进程的标准输出

python - 恢复超时完成的异步子进程返回代码

c++ - 如果任一参数为 NaN,什么会导致 C/C++ <、<= 和 == 运算符返回 true?

c++ - 如何为类 union 类编写析构函数

C 中的 Char 和 if 语句

linux - 在 Linux 上检测 pid 是否为僵尸