如何区分 fifo 可打开内容和可读内容?
How to distinguish fifo openable vs readable content?
我对 Linux 上的 fifo
有点陌生,对 select()
的经验也有限。
我 learned 在 FIFO 的读取端调用 open()
将阻塞,直到写入端完成管道。
可以用O_NONBLOCK
打开fifo的读端,以免阻塞在open()
。然后,您可以 select()
在 readfds 中使用 fifo 的文件描述符,以便了解文件何时可打开 - 是吗?
虽然我现在很困惑:在知道文件是可打开的之后,我随后想知道 fifo 有可读的内容,即我想知道 read()
在 fifo 文件描述符上不会阻塞。为此,我会考虑 select()
使用 readfds 中的 fifo 文件描述符 - 但这似乎与使用 select()
来了解文件是否可打开相冲突。
所以我想总结一下我的问题:我如何使用 select()
知道 1) fifo 读取端的 open()
何时不会阻塞,以及 2) read()
在 fifo 上不会阻塞?
我假设 select()
在读取端解锁以指示 fifo 是可打开的,这似乎是不正确的。看起来 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 );
}
我对 Linux 上的 fifo
有点陌生,对 select()
的经验也有限。
我 learned 在 FIFO 的读取端调用 open()
将阻塞,直到写入端完成管道。
可以用O_NONBLOCK
打开fifo的读端,以免阻塞在open()
。然后,您可以 select()
在 readfds 中使用 fifo 的文件描述符,以便了解文件何时可打开 - 是吗?
虽然我现在很困惑:在知道文件是可打开的之后,我随后想知道 fifo 有可读的内容,即我想知道 read()
在 fifo 文件描述符上不会阻塞。为此,我会考虑 select()
使用 readfds 中的 fifo 文件描述符 - 但这似乎与使用 select()
来了解文件是否可打开相冲突。
所以我想总结一下我的问题:我如何使用 select()
知道 1) fifo 读取端的 open()
何时不会阻塞,以及 2) read()
在 fifo 上不会阻塞?
我假设 select()
在读取端解锁以指示 fifo 是可打开的,这似乎是不正确的。看起来 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 );
}