質問

I'm having some problems with unnamed pipes or "fifos" in C. I have two executable files: One tries to read, the other one tries to write. The reader is meant to be executed only once. I tried to make a simple code to show my problem, so it reads 10 times and then it gets closed. However, the writer should be executed many times (in my original program, it can't be executed twice at once: You have to wait for it to finish to run it again).

The problem with this code is: it only prints the incoming message when another one arrives. It seems that it gets blocked until it receives another message. I don't know what is happening, but it seems the "read" line blocks the program although there is data to read, and it works again when I send new data.

I tried another thing: As you can see the writer closes the file descriptor. The reader opens the file descriptor twice, because it would find EOF and get unblocked if it didn't. I tried eliminating those lines (the writer wouldn't close the fd, the reader would open the fd just once, eliminating the second "open()"). But for some reason, it unblocks if I do that. Why does that happen?

This is my code:

Reader:

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 );
}

Writer:

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 );

}

Thanks in advance. And please excuse my poor English

役に立ちましたか?

解決 3

I've been reading more about unnamed pipes and now I understand the problem. I wrote:

the reader opens the file descriptor twice, because it would find EOF and get unblocked if it didn't. I tried eliminating those lines (the writer wouldn't close the fd, the reader would open the fd just once, eliminating the second "open()"). But for some reason, it unblocks if I do that. Why does that happen?

It unblocks because the other process closes, so the OS closes the file descriptor anyway. That's why although I didn't wrote close(fd) it unblocks.

The only way in which a blocking fifo can unblock is:

1) there is data to read 2) the other program closed the file descriptor. If there is no data to read and the writer closed the file descriptor (even if the file descriptor is open in reader), read() returns 0 and unblocks.

So my solution was: redesign my program so it would have the writer's file descriptor open all the time. Which means: there is only a executable file now. I'm pretty sure I could have done it with two executables, but I would probably need semaphores or something like that to synchronize, so it wouldn't try to read if the writer's fd is closed.

他のヒント

you should use the select call to find out if any data is available on the fd of the pipe.

have a look at

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

You've opened file in blocking mode:

If some process has the pipe open for writing and O_NONBLOCK is clear, read() shall block the calling thread until some data is written or the pipe is closed by all processes that had the pipe open for writing.

Depends on you goals you shoud rather synchronize readers and writers of your pipe, or use non-blocking mode for reader. Read about poll, epoll, select.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top