使用 execv 和输入重定向的 C++ 管道命令

标签 c++ posix exec pipe io-redirection

尝试编写一个处理内部和外部命令的 shell。我一次可以获得内部命令和一个外部命令。

我的问题是如何运行这样的命令:“ls -l | grep lib | wc -l”

我正在使用 fork(),并通过 char*[] 中的 execv() 传递外部命令。

关于如何工作有什么想法吗?我假设使用 pipeline() 或其他东西,但我不确定。

问题的第二部分:如何处理 i/o 重定向?谁能指出我有帮助的地方吗?

编辑 到目前为止,@Alex W 是我的英雄。然而,由于我对 pipeline() 和 dup2() 命令不熟悉,所以我对每个调用和变量的用途有点犹豫。

这是我处理单个外部命令的代码(示例=“ls -l -a”):

    pid_t pid;
    pid = fork();
    if (pid < 0)
    {
        cout << "Fork failed." << endl;
    }
    else if (pid == 0)
    {
        execvp(exec_args[0], exec_args);   //exec_args is a char*[] where 
        _exit (EXIT_FAILURE);              //exec_args[0] contains "/bin/ls"
    }                                          //[1]="ls" and [2]="-l" [3]="-a"
    else
    {
        int status;
        waitpid(pid, &status, 0);
    }
    break;

最佳答案

您确实使用管道,并且在 POSIX 系统中管道的工作方式与文件类似。您可以写入管道并从管道中读取,但如果管道中没有任何内容,则会阻塞。查找有关 Unix 系统调用信息的最佳位置是系统调用的手册页。在 Unix 系统上,您可以在终端中输入 man pipeline。如果您无法访问 Unix 终端,那么只需谷歌搜索“man pipeline”。手册页的好处是它们告诉您给定系统调用要包含哪些库。确保您记住,当使用任何 exec 类型的系统调用时,您正在将一个全新的进程加载到该内存中,并且您正在执行的进程将停止运行。

要使用它,请执行以下操作:

int main()
{
    int id[2];
    int fd[2];
    int fd2[2];
    int fd3[2];
    FILE file;
    int status;
    int sz = 0;
    char buff[1000];
    char buff2[1000];
    string launch[2];
    FILE *fp;

    launch[0] = "./anotherProgramToExecute";
    launch[1] = "./yetAnotherProgram";

    pipe(fd);
    pipe(fd2);
    pipe(fd3);

    for(int i = 0; i < 2; i++)
    {
        id[i] = fork();

        if (id[i] == -1) /* an error occurred */
        {
            perror("Fork failed.\n");
        }
        else if (id[i] == 0) /* this is the child process currently acting */
        {
            if(i == 0)
            {
                dup2(fd[1],1);
            }
            else if(i == 1)
            {
                dup2(fd2[0],0);
                dup2(fd3[1],1);
            }
            execlp(launch[i],launch[i], NULL);
        }
        else /* this is the parent process currently acting */
        {
            sz = read(fd[0], buff, 1000);
            buff[sz] = '\0';
            printf("buff = %s\n",buff);

            close(fd[0]);

            write(fd2[1],buff, 1000);

            read(fd3[0],buff2,1000);

            fp = fopen("bin.txt","w");
            if(fp == NULL)
                printf("Cannot open file.\n");
            else
            {
                fprintf(fp,buff2);
                fclose(fp);
            }

            //printf("Creation of Child Process #%d succeeded!\n",id[i]);
            while(waitpid(id[i], &status, WNOHANG) == 0)
                sleep(0.3);
            if (WIFEXITED(status))
            { 
                // successfully terminated children
            }
            else
            {
                perror("Child has not terminated correctly.\n");
            }
        }
    }
}

关于使用 execv 和输入重定向的 C++ 管道命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10873949/

相关文章:

c++ - 您可以使用 C++ 模板来指定集合类型和该类型的特化吗?

c++ - 树实现给出段错误(核心转储)错误 c++ 11

即使在关闭其输入后,子进程也会挂起

java - 在java代码中执行一个带参数的外部程序

gcc - GCC 如何运行它的其他程序?

c++ - 我怎样才能 std::sqrt(boost::lambda::placeholder1_type)?

c++ - 二维数组Qt,初始化和使用

c - gcc wordexp Posix C 库函数不使用 Linux IFS 环境变量来拆分单词

c - uio.h 和 io.h 有什么区别?

java - 在没有 Runtime.exec() 的情况下执行 java prog? "JavaExecutor"是否存在?