简体   繁体   English

FIFO read() function 卡在 c

[英]FIFO read() function gets stuck in c

I'm trying to read a text file's string from a process, then deliver the string to another process via named pipes on LINUX.我正在尝试从进程中读取文本文件的字符串,然后通过 LINUX 上的命名管道将字符串传递给另一个进程。 The problem is when i type './reader text.txt = receiver' to the console the recieving process' read() function returns an error if i put the line问题是当我在控制台输入“./reader text.txt = receiver”时,如果我输入该行,则接收过程“read() function 返回错误

fcntl(fd, F_SETFL, O_NONBLOCK);

or gets stuck on read() function if i remove it.或者如果我删除它,就会卡在 read() function 上。

heres the process that reads the string (reader)继承人读取字符串的过程(阅读器)

#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;
     }
 }

and heres the recieving process (reciever)这是接收过程(接收者)

#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;

 }

The problem is that you closed the pipe in the first process.问题是您在第一个过程中关闭了 pipe。 A pipe doesn't have any permanent storage, it can only hold data while it's open by at least one process. pipe 没有任何永久存储,它只能在至少一个进程打开时保存数据。 When you close the pipe, the data that you've written to it is discarded.当您关闭 pipe 时,您写入的数据将被丢弃。

As a result, when the second process tries to read from the pipe, there's nothing available.结果,当第二个进程尝试从 pipe 中读取数据时,没有可用的数据。

You need to keep the pipe FD open when you execute the second process.执行第二个过程时,您需要保持 pipe FD 打开。 Get rid of close(fd);摆脱close(fd); in the reader program.在阅读器程序中。

To use a FIFO or pipe, sender and receiver must run concurrently, but you are trying to run them sequentially.要使用 FIFO 或 pipe,发送器和接收器必须同时运行,但您尝试按顺序运行它们。 A FIFO or pipe has no persistent storage, so the system does not allow you to write to one unless unless at least one process has the read end open, so as to be able to read it. FIFO 或 pipe 没有持久存储,因此系统不允许您写入其中一个,除非至少有一个进程打开了读取端以便能够读取它。

Ordinarily, attempts to open a FIFO for writing will block while there are no readers, and vice versa.通常,当没有读取器时,尝试打开 FIFO 进行写入会阻塞,反之亦然。 Your reader is working around this by opening the FIFO for both reading and writing, even though it intends only to write.您的读者正在通过打开 FIFO 进行读取和写入来解决此问题,即使它只打算写入。 You will find that if it tries to send too much data to the FIFO then it blocks, because nothing is reading the data, and pipes / FIFOs have limited buffer capacity.你会发现,如果它试图向 FIFO 发送太多数据,它就会阻塞,因为没有任何东西在读取数据,并且管道/FIFO 的缓冲区容量有限。 When it closes the FIFO's fd, leaving no process with it open, all data previously written to it are lost.当它关闭 FIFO 的 fd 时,没有任何进程打开它,之前写入它的所有数据都将丢失。

Your receiver also erroneously opens the FIFO for both reading and writing, whereas it should open it only for reading.您的接收器也会错误地打开 FIFO 进行读写,而它应该只为读取而打开它。 There being no data to read from it, I would expect attempts to read from it to block indefinitely, unless you put it into non-blocking mode.没有数据可以从中读取,我希望尝试从中读取无限期阻塞,除非您将其置于非阻塞模式。 This seems to be exactly what you describe.这似乎正是你所描述的。

To fix it , I would suggest要修复它,我建议

  1. taking the code that starts the receiver out of the reader.从阅读器中取出启动接收器的代码。 Instead, start the reader and receiver separately.相反,请分别启动阅读器和接收器。 Alternatively, the reader may start out by fork() ing, with the resulting child process execv() ing the receiver.或者,阅读器可以fork()开始,结果子进程execv()接收器。

  2. The reader should open the FIFO with flag O_WRONLY , and the receiver should open it with mode O_RDONLY .读取器应使用标志O_WRONLY打开 FIFO,接收器应使用O_RDONLY模式打开它。

  3. You should find a different way to convey the message length from reader to receiver, or, better, to avoid needing to tell it the message length in advance at all.您应该找到一种不同的方式来将消息长度从阅读器传递到接收器,或者更好地避免需要提前告诉它消息长度。 You could, for instance, send an initial fixed-length message that conveys the length of the main message data, but more typical would be for the receiver to just keep reading data until it sees EOF.例如,您可以发送一个初始的固定长度消息来传达主消息数据的长度,但更典型的情况是接收者只继续读取数据,直到它看到 EOF。

  4. The reader will cause the receiver to see EOF on the FIFO by closing it, either explicitly or by terminating.阅读器将导致接收器通过显式关闭或终止来查看 FIFO 上的 EOF。 This depends on the receiver having it open in read-only mode, however, and there being no other writers.然而,这取决于接收器是否以只读模式打开,并且没有其他写入器。

  5. The reader probably should not attempt to buffer the whole message in memory at once.读者可能不应该尝试一次在 memory 中缓冲整个消息。 It should not, in any case, assume that a write() call will transfer the full number of bytes requested -- the return value will tell you how many actually were transferred.在任何情况下,它都不应该假设write()调用将传输请求的全部字节数——返回值将告诉您实际传输了多少字节。 You need to be prepared to use multiple write() calls in a loop to transfer all the data.您需要准备好在一个循环中使用多个write()调用来传输所有数据。

  6. Similarly, the receiver cannot rely on a single read() call to transfer the full number of bytes requested in one call, even if it has some way to know how many are coming.类似地,接收者不能依赖单个read()调用来传输一次调用中请求的全部字节数,即使它有某种方法可以知道有多少字节。 As with write() , you need to be prepared to use multiple read() s to transfer all the data.write()一样,您需要准备好使用多个read()来传输所有数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM