5

我有一个示例程序:

int main()
{
   const char* fn = "/tmp/tmpfifo";
   int i = mkfifo(fn, 0666);
   int fd = open(fn, O_RDONLY | O_NONBLOCK);
   int flags = fcntl(fd, F_GETFL);
   flags &= ~O_NONBLOCK;
   fcntl(fd, F_SETFL, flags);

   char buf[1024];
   int rd= read(fd, buf, 100);
   cout << rd << endl;
   remove(fn);
   return 0;
}

似乎在从文件描述符中删除非阻塞标志后,read调用应该阻塞,直到将某些内容写入 FIFO,但我的程序总是在没有阻塞和rd=0结果的情况下运行。你能解释一下这种行为吗?谢谢!

4

3 回答 3

2

您看到的行为是预期的。您已完成以下操作:

  1. 使用 打开 FIFO 的读取端O_NONBLOCK,因此写入器不需要存在于 FIFO 上。这保证了open()将立即成功。
  2. O_NONBLOCK在后续读取之前禁用。您现在已经回到了与标准(阻塞)情况等效的位置,即 FIFO 具有读取器和写入器,但写入器关闭了 FIFO。此时,读者应该看到文件结尾,这就是您所看到的。
于 2015-04-13T20:20:35.840 回答
0

真奇怪!我尝试了一个代码,它在没有 O_NONBLOCK 的情况下打开文件,然后分三个阶段进行。尽管 O_NONBLOCK 标志结果重置,第 3 阶段仍不能正确运行!

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main()
{
   char buf[1024];
   int rd;
   const char* fn = "prova.txt";
   int i = mkfifo(fn, 0666);
   int fd = open(fn, O_RDONLY); // | O_NONBLOCK);
   int flags = fcntl(fd, F_GETFL);
   //flags &= ~O_NONBLOCK;
   printf("1) Waits!\t\tflags=0%08o\n",flags);

   rd= read(fd, buf, 100);
   printf("%d %o\n",rd,flags);

   flags |= O_NONBLOCK;
   printf("2) Doesn't wait!\tflags=0%08o\n",flags);
   fcntl(fd, F_SETFL, flags);
   rd= read(fd, buf, 100);
   printf("%d %o\n",rd,flags);  

   //This doen't act the flag ????
   flags &= ~O_NONBLOCK;
   fcntl(fd, F_SETFL, flags);
   flags=fcntl(fd, F_GETFL);
   printf("3) Waits!\t\tflags=0%08o\n",flags);
   rd= read(fd, buf, 100);
   printf("%d %o\n",rd,flags);

   puts("End!");
   return 0;
}

这是命令序列和输出:

sergio@zarathustra:~$ ./a.out &
[2] 6555
sergio@zarathustra:~$ echo xxx >> prova.txt
1) Waits!       flags=000100000
4 100000
2) Doesn't wait!    flags=000104000
0 104000
3) Waits!       flags=000100000
0 100000
End!
sergio@zarathustra:~$ 
于 2015-04-12T09:35:19.283 回答
0

我查看了您的代码,乍一看它似乎应该可以工作。没有返回错误,您似乎没有违反任何规则,但它只是没有阻塞。

所以我继续跟踪read调用,看看它在做什么:

跟踪

它一直到pipe_read 函数,没有任何阻塞尝试。一旦它到达那里,它就会意识到管道的另一端没有人并返回 EOF。

所以这显然是设计使然,但是对于管道,open如果没有写入器,只有调用会尝试阻塞,一旦open返回,它只是假设该管道的另一端必须有写入器,或者您是非阻塞的并准备好处理那个。这有点道理。如果您尝试read从管道中获取但作者不在(或者从一开始就不存在),您不想永远等待在那里。

如果您想等到作家打开管道,请不要O_NONBLOCKopen调用中使用。如果您确实使用O_NONBLOCKin open,那么管道的另一端可能没有任何人,并且read调用可能只会返回 EOF 而不会阻塞。

所以简而言之,当你阅读它时,请确保管道的另一端有人。

于 2015-04-12T09:41:21.140 回答