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

时间:2012-06-03 21:05:31

标签: c++ posix exec pipe io-redirection

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

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

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

关于如何工作的任何想法?我假设使用pipe()或其他东西,但我不确定。

问题的第二部分:如何处理i / o重定向?有人能指点我到某个地方吗?

修改 到目前为止,@ Alex W是我的英雄。但是,由于我是管道()和dup2()命令的新手,我对每个调用和变量的用途有点犹豫。

这是我处理单个外部命令的代码(Example =“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;

2 个答案:

答案 0 :(得分:2)

您确实使用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] = '\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");
            }
        }
    }
}

答案 1 :(得分:0)

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