【问题标题】:named pipes(fifo) program doesn't work命名管道(fifo)程序不起作用
【发布时间】:2013-05-10 18:54:00
【问题描述】:

伙计们!我正在尝试制作我的第一个使用命名管道或 fifo 的程序。客户端向服务器发送正整数。当发送负数时,传输关闭。服务器确定发送的最小数量、最大数量并将这两个值发送回客户端。我遇到的麻烦是打印的最大值和最小值总是为零,我真的不知道如何解决这个问题。这是我目前所拥有的:

client.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

main(){
  int f1,f2;
  int n,a,b;
  printf("Give the number: ");
  scanf("%d",&n);
  while(n >= 0){
    printf("Give the number: ");
    scanf("%d",&n);
  }
  f1=open("fifo1",O_WRONLY);
  f2=open("fifo2",O_RDONLY);
  if(f1<0){
    printf("You can't write in the fifo client");
  }
  if(f2<0){
  printf("You can't read from the fifo client");
  }
  write(f1,&n,sizeof(int));
  read(f2,&a,sizeof(int));
  read(f2,&b,sizeof(int));
  printf("The minimum number is %d\n",a);
  printf("The maximum number is %d\n",b);
  close(f2);
  close(f1);
}

服务器.c

#include <sys/stat.h> 
#include <fcntl.h>   
#include <stdio.h>

int minim=0;
int maxim=0;

int min(int n){
if(n>=0 && minim > n){
minim=n;
}
return minim;
}

int max(int n){
if (n > maxim){
maxim=n;
}
return maxim;
}


main(){
  int f1,f2,a,b,n;
  f1=open("fifo1",O_RDONLY);
  f2=open("fifo2",O_WRONLY);
  if(f1<0){
    printf("error");
  }
  if(f2<0){
    printf("error");
  }
  read(f1,&n,sizeof(int));
  a = min(n);
  b = max(n);
  write(f2,&a,sizeof(int));
  write(f2,&b,sizeof(int));
  close(f1);
  close(f2);
}

【问题讨论】:

  • 你和提问this very similar question的人是同一班还是同一个人?
  • @pilcrow 是的,我是同一个人,但我忘记了该帐户的密码。 :( 但这与我的问题有什么关系?
  • 我觉得这个问题的语气很奇怪:实际上,命名管道确实按照记录的方式工作,您只是很难找出如何正确使用它们。这不是命名管道的错(或内核的错)。
  • @BasileStarynkevitch 你能帮我解决这个问题吗?我一遍又一遍地尝试,但我没有很好的解决方案
  • 你之前做过mkfifo吗?

标签: c linux pipe fifo


【解决方案1】:

这是一个非常简单的解决方案。

对于 1,您需要使用 mkfifo 来制作 fifo。如果您之前在单独的程序中执行过此操作,或者该文件已经存在,但如果没有它,您将一无所获。

对于 2,当您在文件已写入的服务器上读取时,没有 gaurentee。如果客户端首先运行,那么您需要刷新您的 write 调用以确保首先写入 fifo。这可以通过 fsync() 来完成。在该文件描述符上执行 fsync() 后,该文件将被写入,并且您可以保证这些值将在那里供服务器读取。通过让服务器读取 fifo 然后输出它读取的内容来验证这一点。

【讨论】:

  • 我确实用 mkfifo 制作了 fifo1 和一个 fifo2。那么,我所做的一切都有效吗?我不明白我需要在哪里使用 fsync()。你能告诉我具体在哪里吗?
  • 每次写入调用后。当您写入文件描述符时,它实际上并没有写入硬盘驱动器上的文件,而是将其写入 linux 内核中的特殊缓冲区。如果您使用 yoru 程序编写,然后拔掉计算机上的插头,则更改不会反映在文件中。每次写入后,放入 fsync(fd),然后在 fsync 后拔下插头,您会看到文件已被写入,因为您刷新了它。在每次写入后执行以确保其存在(或在最后一次写入后执行)。
  • 另外,不能保证在服务器读取文件之前您正在写入文件。您如何确保正确同步时间?
  • 在 client.c 中写入后,我放入 fsync(f1),在 server.c 中每次写入后,我放入 fsync(f2),但程序无法运行。打印的最大值和最小值都为零。
  • 这是因为客户端和服务器之间存在竞争条件。如果你看看如何 ls | grep 工作,它使用 fifo 将 ls 管道传输到 grep,首先执行 ls,然后执行 grep。它不会一下子发生。您需要的是您的服务器阻止对 fifo 的读取,然后在收到通知更新后读取它。此外,读取从当前文件偏移量开始,因此当您从客户端写入 1 和 2 时,服务器在 2 之后开始读取(即 EOF)。在服务器读取和打开之前,您需要回到开始或关闭客户端的管道。
猜你喜欢
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多