FIFO read()函数卡在c中
我试图从进程中读取文本文件的字符串,然后通过LINUX上的命名管道将字符串传递到另一个进程。问题是,当我在控制台中键入“./reader text.txt=receiver”时,如果我将该行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
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;
}