如何区分fifo openable与可读内容?

时间:2017-10-27 18:37:32

标签: linux nonblocking mkfifo

我对Linux上的fifo有些陌生,对select()的使用经验也很少。

learned在FIFO的读端调用open()将阻塞,直到写端完成管道。

可以使用O_NONBLOCK打开fifo的读取结束,以便不会阻止open()。然后,您可以使用readfds中的fifo文件描述符select()来了解文件何时可以打开 - 是吗?

我现在感到困惑的是:在知道文件可以打开之后,我随后想知道fifo具有可读内容,即我想知道read() fifo文件描述符不会阻塞。为此,我会考虑使用readfds中的fifo文件描述符select() - 但这似乎与使用select()来判断该文件是否可打开相冲突。

所以我想总结一下我的问题:如何使用select()知道1)当fifo的读取端的open()不会阻塞时,以及2)何时read()在fifo上不会阻止?

1 个答案:

答案 0 :(得分:0)

我假设select()在读取端解除锁定以指示fifo是可打开的,这似乎是不正确的。只有当要在fifo中读取数据时,看起来select()才会在读取端解锁。

此测试代码演示了我的观察结果:select()超时;取消注释单个注释行,select()取消阻止fifo文件描述符。

#include <iostream>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <ctime>

#define FIFO "/tmp/foo"

void* sr1( void* arg )
{
  mkfifo( FIFO, 0777 );
  sleep( 3 );
  int fd = open ( FIFO, O_WRONLY );
  //write( fd, "a", 1 );
  std::cout << "t1 opened " << fd << std::endl;
  sleep( 3 );
  close( fd );
  std::cout << "t1 closed " << fd << std::endl;
  return NULL;
}

void* sr2( void* arg )
{
  int fd = open( FIFO, O_RDONLY | O_NONBLOCK );
  std::cout << "t2 opened " << fd << std::endl;
  fd_set readfds;
  FD_ZERO( &readfds );
  FD_SET( fd, &readfds );
  struct timeval ts = { 5, 0 };
  std::cout << "t2 waiting now" << std::endl;
  select( fd + 1, &readfds, NULL, NULL, &ts );
  if ( FD_ISSET( fd, &readfds ) )
  {
    std::cout << "t2 " << fd << " set so select() unblocked" << std::endl;
  }
  else
  {
    std::cout << "t2 " << " select() unblocked at timeout" << std::endl;
  }
  close( fd );
  std::cout << "t2 closed " << fd << std::endl;
  return NULL;
}

int main( int argc, char* argv[] )
{
  pthread_t t1;
  pthread_t t2;

  pthread_create( &t1, NULL, sr1, NULL );
  pthread_create( &t2, NULL, sr2, NULL );

  pthread_join( t1, NULL );
  pthread_join( t2, NULL );
}