我在每个 2 个 FIFO 的读取和写入方面遇到问题
附加代码应允许两个终端之间的通信。通信是通过在当前目录中创建的 2 个 FIFO 进行的。该程序必须打开 2 个 fifo,儿子从 STDIN 读取并放入 fifo1,父亲从另一个 fifo 读取并在终端上打印。以这种方式进行通信,因为对程序的调用是:./myprog fifo1 fifo2(对于第一个终端)和./myprog fifo2 fifo1(对于第二个终端)。该代码无法正常工作,我怀疑子 write() 在 fifo 上执行的效果不佳。希望我解释得好,帮助meeee:'(
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
int main(int argc,char* argv[])
{
if(argc<3)
{
printf("Error: Too few arguments...\n");
exit(-1);
}
char** buffer_in=(char**) malloc(sizeof(char*));
char** buffer_out=(char**) malloc(sizeof(char*));
size_t dim_buff=sizeof(char*);
FILE* stream;
FILE* input;
int fifo_in, fifo_out, num_poll_c, num_poll_f, read_count, i,write_b;
pid_t pid;
ssize_t length;
struct pollfd* fd_set_c=(struct pollfd*) malloc(sizeof(int));//for the child
struct pollfd* fd_set_f=(struct pollfd*) malloc(sizeof(int));//for the father
printf("Write character e press enter:\n");
if((fifo_in=open(argv[1],O_RDWR|O_NONBLOCK))==-1)
perror("error open");
if((fifo_out=open(argv[2],O_RDWR|O_NONBLOCK))==-1)
perror("error open");
if((input=fdopen(STDIN_FILENO,"r"))==NULL)
perror("error fdopen");
if((pid=fork())==-1)
perror("error fork");
while(1)
{
if(pid==0) /*child*/
{
fd_set_c->fd=STDIN_FILENO;
fd_set_c->events=POLLIN;
if((num_poll_c=poll(fd_set_c, 1, -1))==-1)
perror("error poll child");//poll on fifo_in
if((length=getline(buffer_in,&dim_buff,input))==-1)
perror("error getline");
printf("The written word is::%s\n",*buffer_in);/*my control for see what in buffer_in is*/
if((write_b=write(fifo_in,*buffer_in,dim_buff))==-1)
perror("error write");
}
else /*father*/
{
fd_set_f->fd=fifo_out;
fd_set_c->events=POLLIN;
if((num_poll_f=poll(fd_set_f, 1, 5000))==-1)
perror("error poll father");//poll on fifo_out
if((read_count=read(fifo_out,*buffer_out,SSIZE_MAX))==-1)
perror("error read");//read on fifo_out
for(i=0;i<=read_count;i++)
printf("%s",buffer_out[i]);//print on stdout buffer_out
}
}
return 0;
}
The attached code should allow the communication between 2 terminals. The communication is made through 2 FIFO, which are created in the current directory. The program has to open the 2 fifos and the son reads from STDIN and puts on the fifo1 and the father reads from the other fifo and prints on terminal. In this way the communication takes place since the call to the program is: ./myprog fifo1 fifo2 (for the first terminal) and ./myprog fifo2 fifo1 (for the second terminal). The code does not work well, I suspect that the child write() performs on the fifo does not work well. Hoping that I explained well, help meeee :'(
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
int main(int argc,char* argv[])
{
if(argc<3)
{
printf("Error: Too few arguments...\n");
exit(-1);
}
char** buffer_in=(char**) malloc(sizeof(char*));
char** buffer_out=(char**) malloc(sizeof(char*));
size_t dim_buff=sizeof(char*);
FILE* stream;
FILE* input;
int fifo_in, fifo_out, num_poll_c, num_poll_f, read_count, i,write_b;
pid_t pid;
ssize_t length;
struct pollfd* fd_set_c=(struct pollfd*) malloc(sizeof(int));//for the child
struct pollfd* fd_set_f=(struct pollfd*) malloc(sizeof(int));//for the father
printf("Write character e press enter:\n");
if((fifo_in=open(argv[1],O_RDWR|O_NONBLOCK))==-1)
perror("error open");
if((fifo_out=open(argv[2],O_RDWR|O_NONBLOCK))==-1)
perror("error open");
if((input=fdopen(STDIN_FILENO,"r"))==NULL)
perror("error fdopen");
if((pid=fork())==-1)
perror("error fork");
while(1)
{
if(pid==0) /*child*/
{
fd_set_c->fd=STDIN_FILENO;
fd_set_c->events=POLLIN;
if((num_poll_c=poll(fd_set_c, 1, -1))==-1)
perror("error poll child");//poll on fifo_in
if((length=getline(buffer_in,&dim_buff,input))==-1)
perror("error getline");
printf("The written word is::%s\n",*buffer_in);/*my control for see what in buffer_in is*/
if((write_b=write(fifo_in,*buffer_in,dim_buff))==-1)
perror("error write");
}
else /*father*/
{
fd_set_f->fd=fifo_out;
fd_set_c->events=POLLIN;
if((num_poll_f=poll(fd_set_f, 1, 5000))==-1)
perror("error poll father");//poll on fifo_out
if((read_count=read(fifo_out,*buffer_out,SSIZE_MAX))==-1)
perror("error read");//read on fifo_out
for(i=0;i<=read_count;i++)
printf("%s",buffer_out[i]);//print on stdout buffer_out
}
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该使用管道(man 2 pipeline。或共享内存:man shmget)在进程和信号量之间进行通信以保护读/写。在谷歌上查找“生产者/消费者”。
看看这个: http://users.evtek.fi /~tk/rtp/sem-生产者-消费者.c
还有这个:http://knol.google.com/k/ Producer-consumer-问题#
You should use pipes(man 2 pipe. or shared memory: man shmget) for communication between your processes and a semaphore to protect reads/writes. Look for "producer/consumer" on google.
take a look at this: http://users.evtek.fi/~tk/rtp/sem-producer-consumer.c
and this: http://knol.google.com/k/producer-consumer-problem#
你这里一团糟。
父级可能会阻塞 FIFO 的 read() ,因为仍然有打开的可写文件描述符。而打开的可写文件描述符属于父进程本身。由于它在 read() 中被阻止,因此无法写入。
将 FIFO 的打开放在
fork()
之后。以更严格的模式打开:要么只用于写入,要么只用于读取,而不是通配符 O_RDWR。这样您就可以镜像通常应用于 pipeline() 的逻辑。此外,对 STDIN_FILENO 进行 poll() 操作是危险的,因为 stdio 已被缓冲。文件描述符可能没有什么可读取的 - 因为它之前已经全部读出,但位于 stdio 缓冲区内。如果您确实知道自己在做什么,至少尝试禁用缓冲,
man setvbuf
。但在存在 fork() 的情况下我仍然不会这样做:缓冲的数据可能会被读取两次:一次由子级读取,一次由父级读取。You have a mess here.
Parent might block in
read()
from FIFO because there are still open writable file descriptors for it. And the open writable file descriptor belongs to the parent process itself. And since it is blocked in theread()
it can't write into it.Put opening of FIFOs after
fork()
. Open in a stricter mode: either only for writing or only for reading, not wildcard O_RDWR. That way you would mirror the logic generally applied to pipe()s.Additionally, poll()ing on STDIN_FILENO is dangerous, as stdio is buffered. File descriptor might have nothing to read - because it was all already read out before, but is inside the stdio buffer. If you really sure you know what you do, at least try to disable buffering,
man setvbuf
. But I still wouldn't do it in the presence of fork(): buffered data might be read twice: once by child and once by parent.