C++ Fork 子进程,询问子进程的进程列表,在 Linux 中终止一个进程

5
我想创建一个子进程,向子进程发送命令“LISTALL”。子进程应该发出系统命令ps并将其列表返回给父进程。然后,父进程应该选择一个进程并将其杀死。这是我到目前为止的代码,但我在尝试运行时遇到了问题。
#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
#include <iostream>
#include <sys/wait.h>

char* getlistOfProcesses(const char* cmd) 
{
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return (char*)"ERROR";
    char buffer[128];
    char *result = new char[1024];
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            strcat(result, buffer);
    }
    pclose(pipe);
    return result;
}

int spawnGEdit()
{
    pid_t gPid = fork();
    if(gPid == 0)
    {
        execl("gedit", "gedit", NULL);
        exit(-1);
    }
    else
    {
    }
    return 0;
}

int main(int argc, char **argv)
{   
    int P2C[2];
    int C2P[2];
    pipe(P2C);
    pipe(C2P);
    pid_t cPid = fork();
    char cmd[50];
    char* listOfProcesses = new char[1024];
    spawnGEdit();

    if (cPid == 0)
    {
        close(P2C[1]); 
        close(C2P[0]); 
        read(P2C[0], cmd, 10);
        if(strcmp(cmd,"LISTALL") == 0)
        {
            write(C2P[1], getlistOfProcesses("ps"), 1024);
            close(P2C[0]);
            close(C2P[1]);
        }
    }
    else if (cPid > 0)
    {
        close(C2P[1]); 
        close(P2C[0]); 
        write(P2C[1], "LISTALL", 10);
        wait(NULL);
        read(C2P[0], listOfProcesses,1024);
        printf("%s",listOfProcesses); 
        //TODO
        //get user input of a PID
        //kill the PID
        close(C2P[0]);
        close(P2C[1]);
    }
    else
    {
        // fork failed
        printf("Forking failed!\n");
        exit(1);
    }
    return 0;
}

当我尝试编译它时,我遇到了以下错误:

/tmp/cciTPIOZ.o: In function `getlistOfProcesses(char const*)':
test.cpp:(.text+0x53): undefined reference to `operator new[](unsigned long)'
/tmp/cciTPIOZ.o: In function `main':
test.cpp:(.text+0x166): undefined reference to `operator new[](unsigned long)'
/tmp/cciTPIOZ.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cpp:(.text+0x2c0): undefined reference to `std::ios_base::Init::Init()'
test.cpp:(.text+0x2cf): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status

我正在使用以下编译器:

cc test.cpp -o test

我是 popen() 的粉丝。那么你遇到了什么问题?它能编译吗?它会挂起吗?有任何输出显示吗?你尝试了 X,期望 Y,观察到 Z。请描述一下 X、Y 和 Z。 - 2785528
2
如果您查阅popen的文档,您会发现它被声明为:FILE *popen(const char *command, const char *mode)。其中command是一个const char *,但您有一个std::string。这些不是相同的数据类型。在您的cmd上调用.c_str()可能是您需要的(尽管我认为您有更多的错误)。 - Cornstalks
1
你说你正在尝试做A、B、C、D、E和F,但到目前为止你写的代码无法编译。试着做一些更简单的事情,然后逐步增加难度。 - Beta
在main()函数中,您进行了2个fork操作,这是有意为之吗? - Kam
Kam,你是指两个管道吗?如果是的话,是的,因为我需要每个进程都能读写。 - ILikeToLearn
显示剩余4条评论
1个回答

2

第9、53、64行出现编译错误,可以通过以下方式解决:

第9行:FILE* pipe = popen(cmd.data(), "r");

第53行:write(C2P[1], getlistOfProcesses("ps").data(), 1024);

第64行:printf("%s",listOfProcesses.data());

原因:这些函数需要char*作为参数,但是您传递了std::string。您必须使用std::string.data()函数,因为它返回指向由std::string对象表示的字符数组的指针。

至于您在第63行遇到的错误,请参考此处

PS:关于您对问题的修改:

第10行:if (!pipe) return (char*)"ERROR";

第12行:char *result = new char[1024];

第53行(第7行更改):char* getlistOfProcesses(const char* cmd)

一点建议:在读取listOfProcesses之前,在父进程中使用wait(NULL);,并在子进程结束时使用exit(0);

可用代码:

#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
#include <iostream>
#include <sys/wait.h>

char* getlistOfProcesses(const char* cmd) 
{
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return (char*)"ERROR";
    char buffer[128];
    char *result = new char[1024];
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            strcat(result, buffer);
    }
    pclose(pipe);
    return result;
}

int spawnGEdit()
{
    pid_t gPid = fork();
    if(gPid == 0)
    {
        execl("gedit", "gedit", NULL);
        exit(-1);
    }
    else
    {
    }
    return 0;
}

int main(int argc, char **argv)
{   
    int P2C[2];
    int C2P[2];
    pipe(P2C);
    pipe(C2P);
    pid_t cPid = fork();
    char cmd[50];
    char* listOfProcesses = new char[1024];
    spawnGEdit();

    if (cPid == 0)
    {
        close(P2C[1]); 
        close(C2P[0]); 
        read(P2C[0], cmd, 10);
        if(strcmp(cmd,"LISTALL") == 0)
        {
            write(C2P[1], getlistOfProcesses("ps"), 1024);
            close(P2C[0]);
            close(C2P[1]);
        }
        exit(0);
    }
    else if (cPid > 0)
    {
        close(C2P[1]); 
        close(P2C[0]); 
        write(P2C[1], "LISTALL", 10);
        wait(NULL);
        read(C2P[0], listOfProcesses,1024);
        printf("%s",listOfProcesses); 
        //TODO
        //get user input of a PID
        //kill the PID
        close(C2P[0]);
        close(P2C[1]);
    }
    else
    {
        // fork failed
        printf("Forking failed!\n");
        exit(1);
    }
    return 0;
}

谢谢您,我意识到一开始我有多愚蠢了。现在我已经将它们交换为字符数组,因为我认为这样会更容易,但是真的有任何偏好吗? - ILikeToLearn
1
不是的,但当您使用一些标准功能时,必须根据它们所需的参数进行选择。 - Milan Patel
把东西改回char*后,我认为这解决了错误问题,但它仍然无法编译。非常感谢,这很有用。 - ILikeToLearn
谢谢,我明白为什么还会有很多错误,因为需要将所有内容都进行转换和声明,这确实需要一些时间适应。另外感谢您的建议。我已经进行了更改,甚至尝试复制粘贴您写的内容,但似乎仍然无法编译。我已更新原帖。 - ILikeToLearn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接