2

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

我的问题是如何让这样的命令运行:“ls -l | grep lib | 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;
4

2 回答 2

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");
            }
        }
    }
}
于 2012-06-03T21:19:46.403 回答
0

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

于 2012-06-03T21:22:10.397 回答