Uruchamiam test z FIFO i poleceniem systemowym select(). Idea jest taka:

  1. Proces należy spać czekając na wiadomości z FIFO za pomocą polecenia select()
  2. Jeśli nie pojawią się żadne wiadomości, proces należy budzić się co 5 sekund i mówić „jeszcze nic”
  3. Jeśli nadejdzie wiadomość, powinna się ona obudzić, wydrukować wiadomość, a następnie zakończyć

Oto kod UWAGA. Wyjmuję sprawdzanie błędów, aby zaoszczędzić miejsce:

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

Po uruchomieniu procesu 1 czekam dobre 10 sekund, a następnie rozpoczynam proces drugi:

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

Spodziewam się zobaczyć coś takiego:

Nothing yet...0
Nothing yet...0
I got a read of X bytes
It was <some string>

Zamiast tego nic nie widzę, dopóki coś nie wpiszę i nie nacisnę enter dla procesu drugiego, proces pierwszy zwróci ciąg poprawnie ... ale dlaczego pętla nie wyświetla komunikatu?

3
Mike 28 wrzesień 2012, 23:38

2 odpowiedzi

Najlepsza odpowiedź

Ponieważ jesteś w Linuksie, możesz dodać O_NONBLOCK do wywołania open() po stronie czytelnika. Aby uzyskać szczegółowe informacje, zobacz man 7 fifo.

3
alk 29 wrzesień 2012, 17:44

Mężczyzna wybierz:

W systemie Linux select() modyfikuje limit czasu, aby odzwierciedlić ilość czasu nieprzespanego; większość innych implementacji tego nie robi. (POSIX.1-2001 zezwala na oba zachowania).

Dlatego powinieneś ponownie zainicjować tv w pętli. Ale to nie jest przyczyna twojego problemu. Przyczyną jest:

Mężczyzna mkfifo:

Otwarcie FIFO do odczytu normalnie blokuje się, dopóki jakiś inny proces nie otworzy tego samego FIFO do zapisu i na odwrót.

6
Serge 29 wrzesień 2012, 00:00