無法理解 select() 系統調用 (failure to understand select() system call)


問題描述

無法理解 select() 系統調用 (failure to understand select() system call)

I'm running an test with a FIFO and a select() system command. The idea is:

  1. Process one should sleep waiting for messages from the FIFO with a select() command
  2. If no messages come in, process one should wake every 5 seconds and say "nothing yet"
  3. 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.

(by MikeSergealk)

參考文件

  1. failure to understand select() system call (CC BY-SA 3.0/4.0)

#file-descriptor #linux #C #fifo #posix






相關問題

在 Android 中持久化文件描述符 (Persisting File Descriptors in Android)

無法理解 select() 系統調用 (failure to understand select() system call)

文件描述符中實際存儲了多少信息? (How much information is actually stored in a file descriptor?)

為同一個文件描述符創建兩個文件是否定義明確? (Is creating two FILEs for the same file descriptor well-defined?)

Android文件描述符洩漏調試 (Android file descriptor leakage debuging)

C中的文件描述符分配 (File Descriptor Assignment in C)

在某些 linux 程序中關閉奇怪的描述符 (Strange descriptor closing in some linux programs)

c read() 導致錯誤的文件描述符錯誤 (c read() causing bad file descriptor error)

C中系統調用的文件句柄問題 (Filehandle issue with system call in C)

使用 copy_file_range 進行複制加速 (Copy acceleration with copy_file_range)

打開文件過多錯誤,但 99.5% 的 inode 是免費的 (Too many open files error but 99.5% inodes are free)

SIGPIPE 由於文件描述符和進程替換 (SIGPIPE due to file descriptors and process substitution)







留言討論