管道进程未终止

发布于 2025-01-20 18:58:55 字数 3329 浏览 1 评论 0原文

我在实现 myshell 的同时实现了管道。

进入管道的进程有 dup2 (fd[pcount][WRITEEND] ,STDOUT_FILENO) 从管道接收输入的进程有dup2(fd[pcount-1][READEND, STDIN_FILENO]) 然后我关闭了所有的fd。

我运行了所有进程并关闭了父进程中留下的所有管道 fd。

ls |命令中输入grep c,出现grep: (standard input): Bad file detector等错误。会有什么问题呢?我关闭了所有的fd。

** 编辑:

正如你所说,我修改了一些代码。我带来了主程序 我将按位运算符(~)更改为“!”它解决了很多问题(我想我在花了一个漫长的夜晚查看代码后已经失去了冷静)

还有最后一个问题。在后台,程序运行没有任何问题,但在前台,grep打印结果后并没有退出。

对于 ls | grep.c,打印结果,但 grep 并未终止。

如果您能猜出哪个部分可能出现问题,我将不胜感激。

问题变了,所以修改了标题。 **

   int main(void){
    int idx = 0; 
    bool pipe_start_flag = false; 

    char cmdline[MAXLINE]; /* Command line */

    while (1) {
    /* Read */
        // init global variable(pcount, reap_count)
        pcount = 0; reap_count = 0; 

        printf("> ");                   
        fgets(cmdline, MAXLINE, stdin); 
        if (feof(stdin))
            exit(0);

        /* Evaluate */
        eval(cmdline);
    }     
}


void eval(char *cmdline){
        int idx = 0, pidx = 0;
        char * argv[MAXARGS];
        char buffer[MAXARGS];
        char * envp[2] = {"/usr/bin/", "0"}; 
        int fd[MAXPIP][2]; 


        bool pipe_start_flag = false; // this argv print output to the WriteEnd of Pipe; 
        bool pipe_end_flag = false; // this argv input from ReadEnd of Pipe
        
 
        bg = preproc_command(cmdline, &idx); 
        strcpy(buffer, cmdline);  

        while(buffer[idx] != '\0'){
                
            /*check if it is piped process*/
            pipe_start_flag = pipe_end_flag;  // if last process was piping process, then this process is a piped process

            parse_line(&buffer[idx], argv, &idx, &pipe_end_flag); // parse until it meets '\0' or '|'(assign its (index-1) on idx)
            if(pipe_end_flag) // if there is '|' character we set pipe
                pipe(fd[pcount]); 

            if(!builtin_command(argv)){
                pid[pcount] = Fork(); 
                if(pid[pcount] == 0){
                    if(pipe_end_flag){ 
                       dup2(fd[pcount][WRITEEND],STDOUT_FILENO); 
                    }
                    if(pipe_start_flag){
                        dup2(fd[pcount-1][READEND] ,STDIN_FILENO); 
                    }
                    for(int i = 0; i < pcount; i++){
                        close(fd[i][READEND]); 
                        close(fd[i][WRITEEND]); 
                    }
                    if(!pipe_start_flag || pipe_end_flag){ // if it is not the last process
                        close(fd[pcount][READEND]);
                        close(fd[pcount][WRITEEND]); 
                    }

                // we should get input from fd[READEND] and put it on argv 
                execvp(argv[0], argv); 
        
            }
            else{ // parent proce
                if(!bg){
                    pidx = waitpid(-1, NULL, WUNTRACED);
                }
                else{ // background process
                }
                ++pcount; 
            }
            ++idx; 
        }   
        if(pipe_start_flag){ // close pipe in main process
            for(int i = 1; i < pcount ; i++){
                close(fd[i-1][READEND]);
                close(fd[i-1][WRITEEND]);
            }
    }

I implemented pipes while implementing myshell.

The process for entering the pipe has dup2 (fd[pcount][WRITEEND] ,STDOUT_FILENO)
The process of receiving input from the pipe has dup2 (fd[pcount-1][READEND, STDIN_FILENO])
And I closed all fds.

And I ran all the processes and closed all the pipe fd left in the parent process.

And when ls | grep c was entered in the command, an error such as grep: (standard input): Bad file descriptor occurred. What would be the problem? I closed all the fds.

** Edited:

As you said, I modified some of the codes. I brought the main program
and I Changed the Bitwise operator(~) to '!' and it solved a lot of problems (I think I've lost my composure after spending a long night looking at the code)

There is a final problem. In the background, the program runs without any problems, but in the foreground, grep does not exit after printing the results.

For ls | grep.c, the result are printed, but grep is not terminated.

I'd appreciate it if you could guess which part could be the problem.

The problem has changed, so I have revised the title.
**

   int main(void){
    int idx = 0; 
    bool pipe_start_flag = false; 

    char cmdline[MAXLINE]; /* Command line */

    while (1) {
    /* Read */
        // init global variable(pcount, reap_count)
        pcount = 0; reap_count = 0; 

        printf("> ");                   
        fgets(cmdline, MAXLINE, stdin); 
        if (feof(stdin))
            exit(0);

        /* Evaluate */
        eval(cmdline);
    }     
}


void eval(char *cmdline){
        int idx = 0, pidx = 0;
        char * argv[MAXARGS];
        char buffer[MAXARGS];
        char * envp[2] = {"/usr/bin/", "0"}; 
        int fd[MAXPIP][2]; 


        bool pipe_start_flag = false; // this argv print output to the WriteEnd of Pipe; 
        bool pipe_end_flag = false; // this argv input from ReadEnd of Pipe
        
 
        bg = preproc_command(cmdline, &idx); 
        strcpy(buffer, cmdline);  

        while(buffer[idx] != '\0'){
                
            /*check if it is piped process*/
            pipe_start_flag = pipe_end_flag;  // if last process was piping process, then this process is a piped process

            parse_line(&buffer[idx], argv, &idx, &pipe_end_flag); // parse until it meets '\0' or '|'(assign its (index-1) on idx)
            if(pipe_end_flag) // if there is '|' character we set pipe
                pipe(fd[pcount]); 

            if(!builtin_command(argv)){
                pid[pcount] = Fork(); 
                if(pid[pcount] == 0){
                    if(pipe_end_flag){ 
                       dup2(fd[pcount][WRITEEND],STDOUT_FILENO); 
                    }
                    if(pipe_start_flag){
                        dup2(fd[pcount-1][READEND] ,STDIN_FILENO); 
                    }
                    for(int i = 0; i < pcount; i++){
                        close(fd[i][READEND]); 
                        close(fd[i][WRITEEND]); 
                    }
                    if(!pipe_start_flag || pipe_end_flag){ // if it is not the last process
                        close(fd[pcount][READEND]);
                        close(fd[pcount][WRITEEND]); 
                    }

                // we should get input from fd[READEND] and put it on argv 
                execvp(argv[0], argv); 
        
            }
            else{ // parent proce
                if(!bg){
                    pidx = waitpid(-1, NULL, WUNTRACED);
                }
                else{ // background process
                }
                ++pcount; 
            }
            ++idx; 
        }   
        if(pipe_start_flag){ // close pipe in main process
            for(int i = 1; i < pcount ; i++){
                close(fd[i-1][READEND]);
                close(fd[i-1][WRITEEND]);
            }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文