問題描述
無法理解 select() 系統調用 (failure to understand select() system call)
I'm running an test with a FIFO and a select()
system command. The idea is:
- Process one should sleep waiting for messages from the FIFO with a
select()
command - If no messages come in, process one should wake every 5 seconds and say "nothing yet"
- If a message comes in, it should wake up, print the message, then terminate
So here's the code NOTE I'm taking out the error checking to save space:
//process 1's code
int main()
{
int fd, ret;
fd_set rfds;
char buffer[100] = {0};
char * myfifo = "/tmp/myfifo";
struct timeval tv;
tv.tv_sec = 5; // 5 second sleep
tv.tv_usec = 0;
mkfifo(myfifo, 0666); //Make the fifo
fd = open(myfifo, O_RDONLY);
FD_ZERO(&rfds); // clear the flags
FD_SET(fd, &rfds); // set "read" on fd
while((ret = select(fd+1, &rfds, NULL, NULL, &tv)) <= 0) //should be 1 when we're ready to read
{
FD_ZERO(&rfds); //I believe we should clear/reset these every time?
FD_SET(fd, &rfds);
printf("Nothing yet...%d\n",ret);
fflush(stdout);
}
n = read(fd, buffer, 100);
printf("I got a read of %d bytes\nIt was %s\n",n, buffer);
unlink(myfifo);
return 0;
}
Once I have process 1 up and running, I wait a good 10s then I kick off process two:
//Process 2's code
int main()
{
int fd, n, ret;
fd_set rfds;
char buffer[100] = {0};
char * myfifo = "/tmp/myfifo";
fd = open(myfifo, O_WRONLY);
printf("What would you like to send?\n");
fgets(buffer, 100, stdin);
write(fd, buffer, strlen(buffer));
close(fd);
return 0;
}
I'm expecting to see something like:
Nothing yet...0
Nothing yet...0
I got a read of X bytes
It was <some string>
Instead I see nothing, until I type in something and hit enter for process two, process one returns the string correctly... but why isn't the loop printing the message?
參考解法
方法 1:
man select:
On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1-2001 permits either behavior.)
Thus you should reinitialize tv inside the loop. But this is not a cause of your problem. The cause is:
man mkfifo:
Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa.
方法 2:
As you are on Linux you might like to add O_NONBLOCK
to the open()
call on the reader side. For details please see man 7 fifo
.