c - C shell 内的多个管道

标签 c linux shell ipc

谁能告诉我这段代码有什么问题吗?我能够成功写入管道,但当我使用该管道输出端作为另一个命令的输入时,无法获取输出。下面是代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>     //for pid_t fork() and other system calls
#include <signal.h>     //for signal()
#include <sys/types.h>


void command_EXECUTER(char *args[]);
void command_HANDLER(char *args[]);
int pipe_EXECUTER(char *args[], int in, int pos);

void shell_INIT(){

    int is_interactive = isatty(STDOUT_FILENO);

    if(is_interactive){



    }

}

int main(int argc, char *argv[], char **envp){

    char shell_INPUT[1024];
    char *tokens[256];
    int tok_counts = 0;

    while(1){

        memset(shell_INPUT,'\0',sizeof(shell_INPUT));

        printf("\n%s@%s: ",getenv("USER"),getenv("SESSION"));
        fgets(shell_INPUT,1024,stdin);

        if((tokens[0] = strtok(shell_INPUT," \n)\t")) == NULL) continue;

        tok_counts = 1;

        while((tokens[tok_counts] = strtok(NULL, " \n\t")) != NULL) tok_counts++;
        /*
        int i=0;
        while(tokens[i]){
            printf("%s ",tokens[i]);
            i++;
        }
        tokens[tok_counts] = NULL;*/
        command_HANDLER(tokens);

    }


    return 0;
}

int fileIO_EXECUTER(char *args[], int in, int pos){
    int fd;
    pid_t pid;

    if((pid=fork())==0){
        switch(pos){

            case 0: 
                    dup2(fd, STDOUT_FILENO);
                    break;


        }
    }
}

int pipe_EXECUTER(char *args[], int in, int pos){

    int fd[2];
    pid_t pid;
    pipe(fd);

    if((pid=fork())==0){
        printf("%s %s %s %d\n",args[0],args[1],args[2],pid);
        fflush(stdout);
        switch(pos){

            case 0: dup2(fd[1], STDOUT_FILENO);     //first command
                    //close(fd[1]);
                    break;

            case 1: dup2(in, STDIN_FILENO);             //in between command
                    dup2(fd[1], STDOUT_FILENO);
                    //close(fd[1]);
                    break;

            case 2: dup2(in, STDIN_FILENO);         //last command
                    //close(fd[1]);
                    break;

            default: printf("wrong input variable\nexiting");
                     exit(1);   

        }
        if(execvp(args[0],args)==-1) printf("%s: command not found",args[0]); fflush(stdout); kill(getpid(),SIGTERM);

    }else if(pid<0){
        printf("couldn't create child");
        exit(1);
    }else{
        wait(pid);
    }

    return fd[0];

}

void command_EXECUTER(char *args[]){

    pid_t pid;

    if((pid=fork())<0){
        printf("couldn't create the child");
        exit(1);
    }
    else if(pid==0){

        if((execvp(args[0],args))==-1) printf("%s: command not found",args[0]); fflush(stdout); kill(getpid(),SIGTERM);
    }
    else wait(pid);

}

void command_HANDLER(char *args[]){

    int i=0;
    int j=0;
    char spec_chars[100];

    while(args[i]){
        if((strcmp(args[i],">")==0) || (strcmp(args[i],"<")==0) || (strcmp(args[i],"|")==0) || (strcmp(args[i],"&")==0) || (strcmp(args[i],"$")==0)){
            spec_chars[j] = *args[i];
            j++;
        }
        i++;
    }

    if(j==0){
        if(strcmp(args[0],"exit")==0) exit(0);
        else if(strcmp(args[0],"clear")==0) system("clear");
        else command_EXECUTER(args);
    }
    else{

        int in = 0;
        int h = 0;
        int pos=0;
        char data[1024];
        int k=i;
        i = 0;
        while(args[i]){
            if(strcmp(args[i],"|")==0){
                args[i] = (char *)NULL;
                in = pipe_EXECUTER(args,in,pos);
                int n = read(in,data,sizeof(data));
                printf("%s %d\n",data,n);
                fflush(stdout);
                args = args+i+1;

                //printf("%s something %s",args[0],args[1]);
                pos = 1;
                i=0;
            }else if(strcmp(args[i],"<")==0){


            }else if(strcmp(args[i],">")==0){

            }else if(strcmp(args[i],"&")==0){

            }
            else{
                i++;
            }

        }
        in = pipe_EXECUTER(args,in,2);
    }

}

例如,如果我使用

ls | sort

'in' 描述符中会有 ls 但 当通过“排序”访问相同的输出时,它会卡在那里......或者执行该命令的子进程永远不会死亡,并且由于该父进程一直在等待。

最佳答案

'in' descripter will have ls inside it but when that same output is accessed by 'sort' it hangs there

这是由于父进程中没有关闭管道写入端的疏忽造成的,因为sort自然会等到all引用写入端的文件描述符被关闭,确保不会有更多输入到达。因此,在 pipe_EXECUTER() 中,您必须在 return fd[0]; 之前调用 close(fd[1]),当然,调试代码

                int n = read(in,data,sizeof(data));
                printf("%s %d\n",data,n);
必须删除 command_HANDLER() 中的

,以免消耗 sort 的输入。

关于c - C shell 内的多个管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27223748/

相关文章:

linux - 在 linux 中监视文件

c - 获取流程段的开始和结束 C/C++

linux - 如何调用位于其他目录的Makefile?

linux - 如何从 bash 中的 .csv 文件的第一行获取特定列?

c++ - 递归函数不能内联吗?

c - 小型(ish)二维阵列的段错误

c++ - Eclipse CDT 不适用于与 Cygwin 编译器集成的 OpenCV 2.0

linux - Bash 脚本 - 使用 find -exec cp 的 For 循环产生错误 : cp: omitting directory

c - STM32F0使用GCC编程arm-none-eabi : hardfault in __libc_init_array

linux - 如何将 awk 用于压缩文件