在C

时间:2016-07-22 07:56:22

标签: c pipe fifo mkfifo

child_filter必须从pipefd中读取值并将其写入命名管道中。 问题是,如果我试图取消注释注释[3](打开命名管道)该函数不会打印值,它似乎停留在read()调用上。相反,如果我不打开fifo管道,它的工作原理。 我需要命名管道用于其他东西。 我应该修改什么?管道和命名管道冲突可能会一起使用吗? 感谢。

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#define FIFONAME "./my-fgrep-named-pipe"

typedef struct{
    int i;
    int v;
    int word;
    int filename;
    char word_string[250];
    char filename_string[250];
}parameters;

int pipefd[2];
void child_reader(parameters params){
    FILE* fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    if(params.filename==0)
        fp = stdin;
    else
        fp = fopen(params.filename_string, "r");

    close(pipefd[0]);          /* Close unused read end */
    if (fp != NULL){
        while ((read = getline(&line, &len, fp)) != -1) {
            //printf("Retrieved line of length %zu :\n", read);
            //printf("%s", line);
            write(pipefd[1], line, strlen(line));
        }
        fclose(fp);
    }
    free(line);
    printf("child reader > end\n");
    exit(0);
}
void child_filter(parameters params){
    char c;
    char temp[250]; 
    int i=0;
    char *temp2;
    int fifofd;
    close(pipefd[1]);          /* Close unused write pipe end */
    printf("read from pipe\n");
    if( (fifofd = open(FIFONAME, O_WRONLY))  == -1) printf("Error WW\n"); 
    while (read(pipefd[0], &c, 1) > 0){ 
        if (c == '\n' || c == '\r'){
            temp[i] = '\n';
            if(i>0){
                temp2=strtok(temp, "\n");
                //temp2[i] = '\n';
            //  printf("[%s]\n", temp2); 
                write(fifofd, temp2, strlen(temp2));
            }i=0;
        }
        else{
            temp[i] = c;
            i++;
        }
    }
    close(fifofd);
    printf("child filter > end\n");
    exit(0);

}

void child_writer(parameters params){
    char c;
    int fifofd;

    char temp[250]; 
    int i=0;
    char *temp2;

    if( (fifofd = open(FIFONAME, O_RDONLY)) == -1) printf("Error RR\n"); 
    while (read(fifofd, &c, 1) > 0){
        printf("entry > [%c] \n", c);

    }
    printf("exit-------------\n");
    close(fifofd);
    unlink(FIFONAME);
    exit(0);
}

int main(int argc, char *argv[]){
    char* temp1;
    parameters params;
    int forkResult;
    params.i=0;
    params.v=0;
    params.word=0;
    params.filename=0;
    int pid_r, pid_w, pid_f;
    if(argc<2){
        printf("error\n");
        exit(0);
    }

    if(strcmp(argv[1],"-i") == 0)
        params.i++;
    if(strcmp(argv[1],"-v") == 0)
        params.v++;
    if(argc>2){
        if(strcmp(argv[2],"-i") == 0)
            params.i++;
        if(strcmp(argv[2],"-v") == 0)
            params.v++;
    }
    if(params.i == 0 && params.v == 0){         
        params.word++;  
        strcpy(params.word_string, argv[1]);
        if(argc>2){
            params.filename++;
            strcpy(params.filename_string, argv[2]);
        }
    }
    else if(params.i != 0 && params.v != 0){ 
        if(argc>3){
            params.word++;
            strcpy(params.word_string, argv[3]);
        }
        if(argc>4){
            params.filename++;
            strcpy(params.filename_string, argv[4]);
        }
    }
    else{               
        if(argc>2){
            params.word++;
            strcpy(params.word_string, argv[2]);
        }
        if(argc>3){
            params.filename++;
            strcpy(params.filename_string, argv[3]);
        }
    }

    printf("Result: i[%d], v[%d], name[%d], filename[%d]\n", params.i, params.v, params.word, params.filename);

    if(params.word==0){
        printf("Error X\n");
        exit(0);
    }


    if (pipe(pipefd) == -1) {
        printf("pipe error\n");
        exit(0);
    }
    unlink(FIFONAME);
    if( mkfifo(FIFONAME, 0666) != 0) printf("Error fifo1\n"); 

    if( (pid_r=fork()) == 0 ){

        child_reader(params);
    }
    if( (pid_f=fork()) == 0 ){
        child_filter(params);
    }
    if( (pid_w=fork()) == 0 ){
        child_writer(params);
    }
    waitpid(pid_r, NULL, 0);
    printf("Reader finished\n");
    close(pipefd[1]);

    waitpid(pid_f, NULL, 0);
    close(pipefd[0]);

    printf("filter finished\n");

    waitpid(pid_w, NULL, 0);
    printf("Done!\n");
    exit(0);


}

2 个答案:

答案 0 :(得分:1)

如果打开一个命名管道进行写入,它将会阻塞,直到打开另一端进行读取。这是一种预期的行为。

  

我需要其他东西的命名管道

那么,如果没有人从管道读取,那么你可以用管道的写端做什么其他的东西?因此,您必须确保管道中有读取器或延迟打开管道,直到有人准备从中读取。另一个选择是使用O_RDWR打开。

答案 1 :(得分:0)

问题是forks欺骗文件描述符,所以它们仍然打开。 由于这个原因,子进程将无法完成。 固定代码:

    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    #define FIFONAME "./my-fgrep-named-pipe"

    typedef struct{
    int i;
    int v;
    int word;
    int filename;
    char word_string[250];
    char filename_string[250];
    }parameters;

    int pipefd[2];
    void child_reader(parameters params){
    FILE* fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    if(params.filename==0)
            fp = stdin;
    else
            fp = fopen(params.filename_string, "r");

    close(pipefd[0]);          /* Close unused read end */
    if (fp != NULL){
            while ((read = getline(&line, &len, fp)) != -1) {
                    //printf("Retrieved line of length %zu :\n", read);
                    //printf("%s", line);
                    write(pipefd[1], line, strlen(line));
            }
            fclose(fp);
    }
    free(line);
    close(pipefd[1]);          /* Close unused read end */
    printf("child reader > done\n");
    exit(0);
    }
    void child_filter(parameters params){
    char c;
    char temp[250];     
    int i=0;
    char *temp2;
    int fifofd;
    close(pipefd[1]);          /* Close unused write pipe end */

    if( (fifofd = open(FIFONAME, O_WRONLY))  == -1) printf("Error fifoWW\n"); 
    printf("read from pipe\n");
    while (read(pipefd[0], &c, 1) > 0){     
            if (c == '\n' || c == '\r'){
                    temp[i] = '\n';
                    if(i>0){
                            temp2=strtok(temp, "\n");
                            //temp2[i] = '\n';
                            //printf("[%s]\n", temp2); 
                            write(fifofd, temp2, strlen(temp2)); //prima senza +1;
                    }i=0;
            }
            else{
                    temp[i] = c;
                    i++;
            }
    }
    close(fifofd);
    close(pipefd[0]);    
    printf("child filter > done\n");
    exit(0);

    }

    void child_writer(parameters params){
    char c;
    char temp[250];     
    int i=0;
    char *temp2;
    int size;
    int fifofd;
    if( (fifofd = open(FIFONAME, O_RDONLY)) == -1) printf("Error fifoRR\n"); 
    do{
            printf("entry> [%c] \n", c);
            size = read(fifofd, &c, 1);
            printf("next size read> %d\n", size);
    }while(size > 0);
    close(fifofd);
    printf("exit-------------\n");
    //unlink(FIFONAME);
    exit(0);
    }

    int main(int argc, char *argv[]){
    char* temp1;
    parameters params;
    int esitoFork;
    params.i=0;
    params.v=0;
    params.word=0;
    params.filename=0;
    int pid_r, pid_w, pid_f;
    FILE *myfifo;
    if(argc<2){
            printf("error \n");
            exit(0);
    }

    if(strcmp(argv[1],"-i") == 0)
            params.i++;
    if(strcmp(argv[1],"-v") == 0)
            params.v++;
    if(argc>2){
            if(strcmp(argv[2],"-i") == 0)
                    params.i++;
            if(strcmp(argv[2],"-v") == 0)
                    params.v++;
    }
    if(params.i == 0 && params.v == 0){                 // [3] ho il nome, [4] ho il filename
            params.word++;      
            strcpy(params.word_string, argv[1]);
            if(argc>2){
                    params.filename++;
                    strcpy(params.filename_string, argv[2]);
            }
    }
    else if(params.i != 0 && params.v != 0){        // [2] ho il nome, [3] ho il filename
            if(argc>3){
                    params.word++;
                    strcpy(params.word_string, argv[3]);
            }
            if(argc>4){
                    params.filename++;
                    strcpy(params.filename_string, argv[4]);
            }
    }
    else{                               // [3] ho il nome, [4] ho il filename
            if(argc>2){
                    params.word++;
                    strcpy(params.word_string, argv[2]);
            }
            if(argc>3){
                    params.filename++;
                    strcpy(params.filename_string, argv[3]);
            }
    }

    printf("Result: i[%d], v[%d], nome[%d], filename[%d]\n", params.i, params.v, params.word, params.filename);

    if(params.word==0){
            printf("Error syntax\n");
            exit(0);
    }


    if (pipe(pipefd) == -1) {
            printf("pipe error\n");
            exit(0);
    }

    if( mkfifo(FIFONAME, 0666) != 0) printf("Error fifo\n"); 


    if( (pid_r=fork()) == 0 ){

            child_reader(params);
    }
    if( (pid_f=fork()) == 0 ){
            child_filter(params);
    }
    close(pipefd[0]);
    close(pipefd[1]);
    if( (pid_w=fork()) == 0 ){
            child_writer(params);
    }
    waitpid(pid_r, NULL, 0);
    printf("Reader finished\n");

    waitpid(pid_f, NULL, 0);
    printf("filter finished\n");

    waitpid(pid_w, NULL, 0);
    printf("Done!\n");
    unlink(FIFONAME);
    exit(0);
    }