c - 如何在你自己的 Linux shell 中实现管道?

标签 c shell pipe fork execvp

我正在用 C 为 Linux 编写我自己的简单 shell。如果不退出整个 shell,我无法实现管道。我相信我需要再执行一个 fork() 来实现这一点,但我不确定在哪里执行此操作。

我的程序有一个 main():

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void){

    char input[256];
    char* temp = NULL;
    char* args[9];
    char* cmd1[5];
    char* cmd2[5];
    int i, j, pipe_pos;
    int fd[2];

    while(1){

        // set all args to NULL
        for (i = 0; i < 9; i++) {
            args[i] = NULL;
        }

        for (i = 0; i < 5; i++) {
            cmd1[i] = NULL;
            cmd2[i] = NULL;
        }


        // print message to terminal
        printf("My Shell (v2.0):>  ");

        // get input from user
        fgets(input,255,stdin);

        // test if input = 'quit'
        if (!strncmp(input,"quit",4)) {

            // exit program if input = quit
            exit(0);

        }
        else { // continue running program

            // initialise counter
            i = 0;

            // tokenize first word
            temp = strtok(input, " \n");

            // receive arguments from user input
            while ((temp != NULL) && (i < 9)) {

                args[i] = temp;
                temp = strtok(NULL, " \n");
                i++;

            }

            // find position of "|" (pipe)
            j = i - 1;
            pipe_pos = 8;

            for (i = 0; i < j; i++) {
                if (strcmp(args[i],"|") == 0) {
                    pipe_pos = i;
                    break;
                }
            }

            // copy 1st command with arguments to new array
            for (i = 0; i < pipe_pos; i++) {
                cmd1[i] = args[i];
            }

            // copy 2nd command with arguments to new array
            j = 0;
            if (pipe_pos != 8) {
                for (i = pipe_pos+1; i < 9; i++) {
                    // copy if array is not full
                    if (j < 5){

                        cmd2[j] = args[i];
                        j++;

                    } // end if (j < 5)
                } // end for
            } // end if (pipe_pos != 8) {

            // run if program needs piping
            if (pipe_pos != 8) {

                pipeProcesses(cmd1, cmd2);

            }
            else {

                runProcess(cmd1);

            }


        } // end else

    }// end while

    return 0;
}// end main()

pipingProcesses() 函数:

void pipeProcesses(char ** cmd1, char ** cmd2){

    int fd[2];

    pipe(fd);

    if (!fork()) {

        // close STD_OUT
        close(1);
        // make STD_OUT same as fd[1]
        dup(fd[1]);
        // we don't need this
        close(fd[0]);
        runProcess(cmd1);
        exit(0);

    } else {

        // close STD_IN
        close(0);
        // make STD_IN same as fd[0]
        dup(fd[0]);
        // we don't need this
        close(fd[1]);
        execvp(cmd2[0], cmd2);

    }

}

和 runProcess() 函数:

void runProcess(char ** cmd){

    int error;

    // initialise error flag
    error = 0;

    if (fork() == 0) {
        // child process
        error = execvp(cmd[0], cmd);

        // print error: unknown command
        if (error == -1) {
            printf("ERROR: UNKNOWN COMMAND (%s)\n", cmd[0]);
            exit(0);
        }

    }
    else {

        // parent process
        waitpid(0,NULL,0);

    }

}

一切正常,除了我希望 shell 在我通过管道传输两个命令后继续运行。我该如何解决这个问题?

最佳答案

您在主程序的流程中调用 execvp(cmd2[0], cmd2);,用 cmd2 替换您的程序。

您也应该为该命令使用 fork()。

关于c - 如何在你自己的 Linux shell 中实现管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31926558/

相关文章:

string - 在shell脚本中将查询结果转换为数组

bash - 如何在 Bash 中检测 OpenSSL 的失败

python - 如何让 Python 脚本在退出时退出 shell?

C - 使用管道、选择、fork 和 execl 创建进程树

c - 数组值计数

c - PAM pam_sm_close_session 没有启动

python - python逐行读取管道输出

unix - 如何将原始 PCM 数据从/dev/ttyUSB0 传输到声卡?

cppcheck 空指针取消引用,但它实际上可以变成 null

c - 从套接字读取然后分割输入字符串在 C 中的行为不正常