【问题标题】:How to distinguish fifo openable vs readable content?如何区分 fifo 可打开内容和可读内容?
【发布时间】:2017-10-27 18:37:32
【问题描述】:

我对 Linux 上的 fifos 有点陌生,并且对 select() 的经验也有限。

我已经learned 表示,在 FIFO 的读取端调用 open() 将阻塞,直到写入端完成管道。

可以使用O_NONBLOCK 打开fifo 的读取端,以免在open() 处阻塞。然后您可以select() 在 readfds 中使用 fifo 的文件描述符,以便知道文件何时可打开 - 是吗?

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

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

【问题讨论】:

    标签: linux nonblocking mkfifo


    【解决方案1】:

    我假设select() 在读取端解除阻塞以表明先进先出是可打开的,这似乎是不正确的。看起来select()只有在fifo中有数据要读取时才会在读取端解除阻塞。

    这个测试代码证明了我的观察: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 );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 2011-02-21
      • 2017-10-08
      • 1970-01-01
      • 2011-06-02
      相关资源
      最近更新 更多