虽然有数据要读取,但未命名的管道会被阻止

时间:2014-05-13 05:42:10

标签: c++ concurrency pipe

我对未命名的烟斗或" fifos"有一些问题。在C.我有两个可执行文件:一个尝试读取,另一个尝试写入。读者只能执行一次。我试着制作一个简单的代码来显示我的问题,所以它会读取10次然后关闭。但是,作者应该被执行多次(在我的原始程序中,它不能一次执行两次:你必须等待它再次运行它。)

此代码的问题是:它仅在另一个消息到达时打印传入消息。它似乎被阻止,直到收到另一条消息。我不知道发生了什么,但似乎是"阅读"尽管有数据要读取,但是行阻止程序,当我发送新数据时,它会再次起作用。

我尝试了另一件事:你可以看到编写器关闭了文件描述符。阅读器打开文件描述符两次,因为它会找到EOF并且如果它没有被取消阻止。我尝试消除这些线条(作者不会关闭fd,读者只会打开fd一次,消除第二个" open()")。但出于某种原因,如果我这样做,它会解除阻碍。为什么会这样?

这是我的代码:

阅读器:

int main () {

int fd;

static const std::string FILE_FIFO = "/tmp/archivo_fifo";

mknod ( static_cast<const char*>(FILE_FIFO.c_str()),S_IFIFO|0666,0 );

std::string mess = "Hii!! Example";

//open:
fd = open ( static_cast<const char*>(FILE_FIFO.c_str()),O_WRONLY );

//write:
write ( fd, static_cast<const void*>(mess.c_str()) ,mess.length() );

std::cout << "[Writer]  I wrote " << mess << std::endl;

//close:
close ( fd );
fd = -1;

std::cout << "[Writer] END" << std::endl;
exit ( 0 );
}

编剧:

int main () {
int i,fd;
static const int BUFFSIZE = 100;
static const std::string name = "/tmp/archivo_fifo";
mknod ( static_cast<const char*>(name.c_str()),S_IFIFO|0666,0 );
char buffer[BUFFSIZE];

i=0;
fd = open ( name.c_str(),O_RDONLY );
while (true) {
    i++;
    std::cout << "Waiting to read Fifo: "<< i << std::endl;
    ssize_t bytesLeidos = read ( fd,static_cast<void*>(buffer),BUFFSIZE);
    fd = open ( name.c_str(),O_RDONLY );
    std::string mess = buffer;
    mess.resize ( bytesLeidos );
    std::cout << "[Reader] I read: " << mess << std::endl;
    sleep(3);
    if (i==10) break;

}
close ( fd );
fd = -1;
unlink ( name.c_str() );

std::cout << "[Reader] END" << std::endl;
exit ( 0 );

}

提前致谢。请原谅我可怜的英语

3 个答案:

答案 0 :(得分:0)

你应该使用select调用来查明管道fd上是否有任何数据。

看看

http://en.wikipedia.org/wiki/Select_(Unix)

答案 1 :(得分:0)

您已在blocking mode中打开文件:

  

如果某个进程打开了管道并且O_NONBLOCK已清除,则read()将阻塞调用线程,直到写入一些数据或管道被管道打开以供写入的所有进程关闭。

取决于您的目标,您应该与管道的读者和作者同步,或者为读者使用非阻止模式。阅读poll, epoll, select

答案 2 :(得分:0)

我一直在阅读更多有关未命名管道的信息,现在我明白了这个问题。我写道:

  

阅读器打开文件描述符两次,因为它会找到EOF并且如果没有则会被取消阻止。我尝试消除那些行(作者不会关闭fd,读者只会打开fd一次,消除第二个“open()”)。但出于某种原因,如果我这样做,它会解除阻碍。为什么会这样?

它取消阻止,因为其他进程关闭,因此操作系统无论如何都会关闭文件描述符。这就是为什么虽然我没有写关闭(fd)它解除阻塞。

阻止fifo可以取消阻止的唯一方法是:

1)有数据需要阅读 2)其他程序关闭文件描述符。如果没有要读取的数据且编写器关闭了文件描述符(即使文件描述符在阅读器中打开),read()也会返回0并取消阻塞。

所以我的解决方案是:重新设计我的程序,这样就可以让编写器的文件描述符一直打开。这意味着:现在只有一个可执行文件。我很确定我可以使用两个可执行文件来完成它,但我可能需要信号量或类似的东西来进行同步,因此如果编写器的fd已关闭,它就不会尝试读取。