FIFO read()函数卡在c中

FIFO read()函数卡在c中,c,linux,pipe,named-pipes,C,Linux,Pipe,Named Pipes,我试图从进程中读取文本文件的字符串,然后通过LINUX上的命名管道将字符串传递到另一个进程。问题是,当我在控制台中键入“./reader text.txt=receiver”时,如果我将该行 fcntl(fd, F_SETFL, O_NONBLOCK); 或者如果我删除read()函数,它就会被卡住 下面是读取字符串的过程(读取器) #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 int main(int argc,char*argv1[]{ 如果(argc==4&&s

我试图从进程中读取文本文件的字符串,然后通过LINUX上的命名管道将字符串传递到另一个进程。问题是,当我在控制台中键入“./reader text.txt=receiver”时,如果我将该行

fcntl(fd, F_SETFL, O_NONBLOCK);
或者如果我删除read()函数,它就会被卡住

下面是读取字符串的过程(读取器)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv1[]{
如果(argc==4&&strcmp(argv1[2],“=”)==0){
char mesaj[99999];//要传递的消息
字符行[150];
FILE*fp=fopen(argv1[1],“r”);//读取文本文件
如果(fp==NULL){
printf(“文本文件错误!”);
出口(1);
}
while(fgets(line,sizeof(line),fp)){
strcat(mesaj,行);//将每一行附加到消息中
}
fclose(fp);
mesaj[strlen(mesaj)-1]='\0';
int n=strlen(mesaj)+1;
//printf(“获取文本%s\n”,mesaj);
如果(mkfifo(“myFifo”,0777)=-1&&errno!=EEXIST){
printf(“管道错误”);
出口(1);
}
printf(“期初”);
int fd=打开(“myFifo”,O_RDWR);
如果(fd==-1){
printf(“打开错误”);
出口(1);
}
printf(“公开”);
如果(写入(fd,mesaj,sizeof(char)*n)=-1){
printf(“写入错误”);
出口(1);
}
printf(“书面”);
关闭(fd);
printf(“已关闭”);
fflush(stdout);
char mesajSizeChar[n];
sprintf(mesajSizeChar,“%d”,n);
char*args[]={mesajSizeChar,NULL};//将消息大小作为另一个进程的参数发送
字符程序[]=“/”;
strcat(程序,argv1[3]);//收到的进程名作为参数
execv(program,args);//调用另一个进程
perror(“execv”);
返回0;
}
}
这是接收过程(receiver)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv1[]{
int mesajSize=atoi(argv1[0]);//将消息大小转换为整数
char-mesaj[99999];
printf(“\n此处命名\n”);
int fd=打开(“myFifo”,O_RDWR);
fcntl(fd、F_设置FL、O_非块);
printf(“\n打开\n”);
如果(fd==-1)
printf(“管道错误\n”);
如果(读取(fd、mesaj、sizeof(char)*mesajSize)=-1)
printf(“读取错误\n”);
printf(“读取\n”);
printf(“\n加工:%s\n”,mesaj);
关闭(fd);
返回0;
}

问题在于您在第一个过程中关闭了管道。管道没有任何永久存储,它只能在至少一个进程打开时保存数据。关闭管道时,写入管道的数据将被丢弃

因此,当第二个进程尝试从管道中读取时,没有可用的内容


执行第二个进程时,需要保持管道FD打开。摆脱
close(fd)

要使用FIFO或管道,发送器和接收器必须同时运行,但您正在尝试按顺序运行它们。FIFO或管道没有持久性存储,因此系统不允许写入,除非至少有一个进程打开了读取端,以便能够读取它

通常,在没有读卡器的情况下,打开FIFO进行写入的尝试将被阻止,反之亦然。您的读者正在通过打开FIFO进行读写来解决这个问题,即使它只打算写。您会发现,如果它试图向FIFO发送太多数据,那么它就会阻塞,因为没有任何东西在读取数据,并且管道/FIFO的缓冲容量有限。当它关闭FIFO的fd时,没有任何进程处于打开状态,以前写入它的所有数据都将丢失

您的接收器还错误地打开FIFO进行读取和写入,而它应该只打开FIFO进行读取。由于没有数据可从中读取,我希望从中读取的尝试会无限期地阻塞,除非您将其置于非阻塞模式。这似乎正是你所描述的

要修复它,我建议

  • 从读卡器中取出启动接收器的代码。相反,分别启动读卡器和接收器。或者,读卡器可以从
    fork()
    ing开始,产生的子进程
    execv()
    ing接收器


  • 读卡器应使用标志
    O_WRONLY
    打开FIFO,接收器应使用模式
    O_RDONLY
    打开FIFO

  • 您应该找到一种不同的方式将消息长度从读者传达给接收者,或者更好地避免事先告诉它消息长度。例如,您可以发送一条初始固定长度的消息,该消息传递主消息数据的长度,但更典型的是,接收方只需继续读取数据,直到看到EOF

  • 读卡器通过显式关闭或终止FIFO,使接收器在FIFO上看到EOF。但是,这取决于接收器是否以只读模式打开,并且没有其他写入程序

  • 读者可能不应该试图一次在内存中缓冲整个消息。在任何情况下,它都不应该假设
    write()
    调用将传输请求的完整字节数——返回值将告诉您实际传输了多少字节。您需要准备在循环中使用多个
    write()
    调用来传输所有数据

  • 类似地,接收方不能依靠单个
    read()
    调用来传输一次调用中请求的完整字节数,即使它有办法知道有多少字节将要到来。与
    write()
    一样,您需要准备好使用多个
    read()
    来传输所有数据


  • 读卡器应在
    O_WRONLY
    模式下打开FIFO,接收器应在
    O_RDONLY
    模式下打开FIFO。在调用
    strcat()之前,需要将
    mesaj
    初始化为空字符串
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/wait.h> 
    
     int main(int argc,char *argv1[]){
    
     if(argc==4 && strcmp(argv1[2],"=") == 0){
    
     char mesaj[99999]; //message to be delivered
    
        char line[150];
        FILE *fp =fopen(argv1[1],"r");  //reading from a text file
    
        if(fp==NULL){
    
            printf("text file error!");
            exit(1);
        }
    
    
        while(fgets(line,sizeof(line),fp)){
            strcat(mesaj,line); //append every line to message
    
        }
    
        fclose(fp);
    
        mesaj[strlen(mesaj)-1]='\0';
    
        int n =strlen(mesaj)+1;
    
    
       //printf("got the text  %s\n",mesaj);
    
    
        if(mkfifo("myFifo",0777)== -1 && errno!= EEXIST){ 
            printf("Pipe error");
            exit(1);
        }
    
    
        printf("opening\n");
        int fd= open("myFifo",O_RDWR);
        if(fd==-1){
            printf("open error");
            exit(1);
        }
        printf("opened");
    
    
        if( write(fd, mesaj,sizeof(char)*n)==-1){
            printf("write error");
            exit(1);
        }
    
    
        printf("written");
    
        close(fd);
    
        printf("closed");
        fflush(stdout);
    
    
       char mesajSizeChar[n];
       sprintf(mesajSizeChar, "%d", n);
    
    
        char *args[]={mesajSizeChar,NULL}; //send the message size as parameter for the other process
        char program[]="./";
        strcat(program,argv1[3]); // recieved process name as parameter
        execv(program,args); // call the other process
        perror("execv");
    
    
        return 0;
         }
     }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <fcntl.h>
    
    int main(int argc,char *argv1[]){
    
    int mesajSize=atoi(argv1[0]); //convert message size to integer
    char mesaj[99999];
    
    printf("\ncame here\n");
    
    
    int fd= open("myFifo",O_RDWR);
    fcntl(fd, F_SETFL, O_NONBLOCK);
    printf("\nopen \n");
    
    if(fd==-1)
        printf("pipe error\n");
    
    
    if(read(fd,mesaj,sizeof(char)*mesajSize)==-1)
    printf("read error\n");
    
    
    printf("read \n");
    printf("\nworked: %s \n",mesaj);
    
    close(fd);
    return 0;
    
     }