我有一个问题,我必须从命名管道读取。我必须处理命名管道的编写器来去的情况,但我需要在我的应用程序中保持相同的管道打开。
我已在以下代码中对此进行了总结。
int main( int c, char *v[] )
{
int rfd;
if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
{
perror( "open" );
return 1;
}
char buffer[ 1024000 ];
// used to give select an upper bound on number of fds
int nfd = rfd + 1;
fd_set rfds;
FD_ZERO( &rfds );
FD_SET( rfd, &rfds );
while( true )
{
int nr = select( nfd, &rfds, NULL, NULL, NULL );
if ( nr < 0 )
{
perror( "select" );
break;
}
if ( FD_ISSET( rfd, &rfds ) )
{
//std::cout << "RFD SET" << std::endl;
// Ok, we have data we can read
int nread = read( rfd, buffer, sizeof( buffer ) );
if ( nread < 0 )
{
perror( "read" );
break;
}
else if ( nread == 0 )
{
std::cout << "read 0" << std::endl;
}
else
{
std::cout << "read " << nread << " bytes" << std::endl;
}
}
}
close( rfd );
return 0;
}
我遇到的问题是,在第一个进程写入命名管道并断开连接(关闭)之后,我的程序不会阻止选择。它有效地具有rfd设置,并且读取返回在紧密循环中读取的零字节。
我需要rfd处于NON_BLOCKING模式,否则open会阻塞,直到作家出现。
我尝试使用fcntl设置为BLOCKING模式,但这也不起作用。
我对管道语义的有限理解使我认为我需要清除管道上的EOF状态,以便select现在会阻塞。但是,我不知道该怎么做。
我把自己投入到你的集体智慧中:) 标记
答案 0 :(得分:4)
好的,我已经提出了一个解决方案,但我并不满意。如果你问我,这有点像“敲打坚果”。
.....
else if ( nread == 0 )
{
std::cout << "read 0" << std::endl;
FD_ZERO( &rfds );
close( rfd );
if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
{
perror( "re-open" );
break;
}
FD_SET( rfd, &rfds );
nfd = std::max( wfd, rfd ) + 1;
}
else
.....
基本上,我关闭并重新打开管道。
我仍然欢迎更好的解决方案。
答案 1 :(得分:1)
在其他帖子上找到:
if ( (rfd = open( PIPENAME, O_RDWR | O_NONBLOCK )) < 0 )
即。打开RDWR而不是RDONLY似乎有用......
答案 2 :(得分:-1)
您是否尝试在非阻止模式下打开fds,当read()
返回EWOULDBLOCK
/ EAGAIN
时,在fd上执行clearerr()