带有 execv 和输入重定向的 C++ 流水线命令

c++ pipelining commands with execv and input redirection

本文关键字:C++ 流水线 命令 重定向 execv 输入 带有      更新时间:2023-10-16

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

我的问题是如何运行这样的命令:"ls -l |格雷普图书馆 |wc -l"

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

关于如何解决这个问题的任何想法?我假设使用 pipe() 或其他东西,但我不确定。

问题的第二部分:如何处理 I/O 重定向?谁能指出我有用的地方?

编辑到目前为止,@Alex W是我的英雄。但是,由于我对pipe()和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;

您确实使用pipe,并且在 POSIX 系统中,管道的工作方式与文件类似。 您可以写入管道并从管道读取,但如果管道中没有任何内容,则会阻塞。 查找有关 Unix 系统调用的信息的最佳位置是系统调用的手册页。 在Unix系统上,您需要在终端中键入man pipe。 如果您无法访问Unix终端,那么只需谷歌"man pipe"。 手册页的好处是它们告诉您要为给定的系统调用包含哪些库。 确保您记住,当使用任何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] = '';
            printf("buff = %sn",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");
            }
        }
    }
}

我见过的关于管道的最好的在线教程,这是一个老式的,但也是一个好东西:http://beej.us/guide/bgipc/。 您可以浏览它。 有人怀疑你会喜欢它。