【问题标题】:Two programs communicating with FIFOs work with for loop but not with while loop与 FIFO 通信的两个程序使用 for 循环但不能使用 while 循环
【发布时间】:2017-04-25 12:11:04
【问题描述】:

我正在尝试编写两个程序,它们将通过 C 中的 FIFO 进行通信。我正在尝试使用 FIFO 来完成我的任务。

当我知道消息的数量并使用 for 循环读取它们时,它会打印出从另一端发送的所有消息。如果我使用 while 循环,它只会发送其中两个。代码从这个问题How to send a simple string between two programs using pipes?略有改动

这行得通:

/* writer */
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";

    /* create the FIFO (named pipe) */


    /* write "Hi" to the FIFO */
    fd = open(myfifo, O_WRONLY);
    int i;
    for(i = 0; i < 10; i++)
         write(fd, "Hi", sizeof("Hi"));
    close(fd);



    return 0;
}

还有:(已编辑)

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

#define MAX_BUF 1024

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

     mkfifo(myfifo, 0666);
    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    int i;
    for(i = 0; i < 10; i++)
    {
        int n = read(fd, buf, MAX_BUF);
        printf("n = %d , Received: %s\n",n, buf);
    }
    close(fd);

     /* remove the FIFO */
    unlink(myfifo);

    return 0;
}

编辑:现在打印出来

n = 18 , Received: Hi
n = 12 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi
n = 0 , Received: Hi

当我将阅读器改为这个时,它不起作用:

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

#define MAX_BUF 1024

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

     mkfifo(myfifo, 0666);
    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    int i;
    while(read(fd, buf, MAX_BUF))
        printf("Received: %s\n", buf);

    close(fd);

     /* remove the FIFO */
    unlink(myfifo);

    return 0;
}

我在两个单独的终端中运行这两个程序。 当我用第二个阅读器运行它们时,它只会打印出来:

Received: Hi
Received: Hi

任何帮助将不胜感激。

【问题讨论】:

  • 如果你不检查read()的结果,你怎么知道第一个版本有效?如果它没有读取任何内容buf 将保留它以前的内容
  • @IngoLeonhardt 你是对的。刚刚编辑了答案,它一直打印出 0 作为返回值。你对我应该怎么做有什么建议吗?

标签: c pipe fifo


【解决方案1】:

管道是基于流的,而不是基于消息的。虽然读取的字节数应该与写入的数量相匹配,但read 调用的数量不一定与write 调用的数量相同。

如果我们修改阅读器以打印接收到的字节数:

int len;
while((len=read(fd, buf, MAX_BUF)) > 0) {
    printf("Received %d: %s\n", len, buf);
}

我得到以下输出:

Received 30: Hi

所以在第二种情况下,有 10 次写入 3 个字节(2 次用于字母 Hi,1 次用于空终止字节)和 1 次读取 30 字节。在每个 write 调用上写入 3 个字节的原因是字符串常量 "Hi" 的类型为 char [3]

您只看到打印了一个“Hi”实例,因为第三个字节是终止字符串的空字节,因此没有打印任何内容。

【讨论】:

  • 我明白了,我在试验时也注意到了这一点,但我仍然不知道让他们不断交流的最佳方式是什么。
  • 我接受这个答案。因为它让我意识到我不应该在管道内写空值,因为它弄乱了另一端。我将代码更改为“sizeof("Hi")-1”,现在它会打印出一堆 Hi。谢谢。
【解决方案2】:

在第二个版本中,循环的继续执行取决于read() 返回的值,而在第一个版本中,它无条件循环十次。

并且由于它不清除缓冲区,只要第一次迭代读取“Hi”,所有后续迭代都会打印“Hi”,无论read() 成功、部分成功或失败。

【讨论】:

  • 正如您编辑中的输出所示,前两次读取中读取了十次写入的所有数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
相关资源
最近更新 更多