【问题标题】:*Almost* Perfect C Shell Piping*几乎*完美的 C 壳管道
【发布时间】:2012-09-22 15:28:10
【问题描述】:

我正在用 C 语言编写一个小型 linux shell,并且非常接近完成。我接收来自用户的命令并将其存储在 args 中,由空格分隔。在以下示例中,假设 args 包含以下内容:

args[] = {"ls", "-l", "|", "wc"};

我的函数接受 args 并接受有多少 管道。我已经尽可能多地注释了我的代码。这里是:

int do_command(char **args, int pipes) {
    // The number of commands to run
    const int commands = pipes + 1;
    int i = 0;

    int pipefds[2*pipes];

    for(i = 0; i < pipes; i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("Couldn't Pipe");
            exit(EXIT_FAILURE);
        }
    }

    int pid;
    int status;

    int j = 0;
    int k = 0;
    int s = 1;
    int place;
    int commandStarts[10];
    commandStarts[0] = 0;

    // This loop sets all of the pipes to NULL
    // And creates an array of where the next
    // Command starts

    while (args[k] != NULL){
        if(!strcmp(args[k], "|")){
            args[k] = NULL;
            // printf("args[%d] is now NULL", k);
            commandStarts[s] = k+1;
            s++;
        }
        k++;
    }



    for (i = 0; i < commands; ++i) {
        // place is where in args the program should
        // start running when it gets to the execution
        // command
        place = commandStarts[i];

        pid = fork();
        if(pid == 0) {
            //if not last command
            if(i < pipes){
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command&& j!= 2*pipes
            if(j != 0 ){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            int q;
            for(q = 0; q < 2*pipes; q++){
                    close(pipefds[q]);
            }

            // The commands are executed here, 
            // but it must be doing it a bit wrong          
            if( execvp(args[place], args) < 0 ){
                    perror(*args);
                    exit(EXIT_FAILURE);
            }
        }
        else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        j+=2;
    }

    for(i = 0; i < 2 * pipes; i++){
        close(pipefds[i]);
    }

    for(i = 0; i < pipes + 1; i++){
        wait(&status);
    }
}

我的问题是,虽然程序有点正确执行,但它的行为很奇怪,我希望你能帮助我。

例如 hen 我运行 ls | wc,输出是ls | wc,但它也会在其下方打印一个简单的 ls 的输出,即使它应该只是输出的 wc

作为另一个例子,当我尝试 ls -l | wcwc的第一个数字出现,但随后ls -l的输出显示在它的下方,即使它应该只是wc 的输出。

提前致谢! :)

【问题讨论】:

  • 在这里工作。你确定你用正确的参数调用你的函数吗?
  • 在这里也可以正常工作。顺便说一句,do_command 没有按应有的方式返回。
  • 有效?!哈哈。它是否 100% 正确工作?就像您在实际的 linux 框中的程序之外键入 ls -l | wc 一样,它的输出与我的代码中的输出是否相同?
  • 我只试过ls | wc,但是是的,它有相同的输出。
  • 存在一个影响ls -l | wc 的错误(实际上是ls -l | wc -l)。除此之外,它对我有用。你应该试试strace -f yourprogram 看看它到底做了什么。

标签: c linux shell pipe


【解决方案1】:

好的,我发现了一个小错误。这个

       if( execvp(args[place], args) < 0 ){

应该是

       if( execvp(args[place], args+place) < 0 ){

您的版本将 args 用于所有其他命令的第一个命令。除此之外,它对我有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    相关资源
    最近更新 更多