Читать из названного канала - PullRequest
0 голосов
/ 08 января 2019

Мне нужно написать программу, которая контролирует два именованных канала и печатает информацию, отправленную через них.

Когда конец записи одного из каналов закрыт, программа обнаружит это, закроет и снова откроет канал.

Это то, что я написал до сих пор:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define BUF_SIZE 200

int
main(void)
{
   fd_set rfds;
   struct timeval tv;
   int retval;
   ssize_t n_read;
   char buf[BUF_SIZE];

   /* Open pipes */
   int tuberia1_fd = open("tuberia1",O_RDONLY);
   int tuberia2_fd = open("tuberia2",O_RDONLY);

   while(1){
       /* Watch stdin (fd 0) to see when it has input. */
       FD_ZERO(&rfds);
       FD_SET(0, &rfds);

       /* Wait for an indefinite amount of time. */
       tv.tv_sec = 0;
       tv.tv_usec = 0;

       retval = select(2, &rfds, NULL, NULL, &tv);
       /* Don't rely on the value of tv now! */

       if (retval == -1)
           perror("select()");
           exit(EXIT_FAILURE);

       if(FD_ISSET(tuberia1_fd, &rfds)){
           n_read = read(tuberia1_fd, &buf, BUF_SIZE);
           if (n_read == 0){
               close(tuberia1_fd);
               tuberia1_fd = open("tuberia1", O_RDONLY);
           }else{
               buf[n_read] = '\0';
               printf("tuberia1: %s", buf);
           }
       } else if (FD_ISSET(tuberia2_fd, &rfds)){
           n_read = read(tuberia2_fd, &buf, BUF_SIZE);
           if (n_read == 0){
               close(tuberia2_fd);
               tuberia2_fd = open("tuberia2", O_RDONLY);
           }else{
               buf[n_read] = '\0';
               printf("tuberia2: %s", buf);
           }
       }
   }
}

Когда я запускаю его, программа блокируется, что является ожидаемым поведением. Но когда я echo hello_world > tuberia1 нет ответа от программы.

Что происходит?

РЕДАКТИРОВАТЬ: Как заметил GM ниже, я неправильно передавал аргументы select. После исправления, что моя программа выглядит так:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define BUF_SIZE 200

int
main(void)
{
   fd_set rfds;
   struct timeval tv;
   int retval;
   ssize_t n_read;
   char buf[BUF_SIZE];

   /* Open pipes */
   printf("Opening tuberia1");
   int tuberia1_fd = open("tuberia1",O_RDONLY);
   printf("Opening tuberia2");
   int tuberia2_fd = open("tuberia2",O_RDONLY);

   while(1){
       printf("Enter the loop");
       /* Watch stdin (fd 0) to see when it has input. */
       FD_ZERO(&rfds);
       FD_SET(tuberia1_fd, &rfds);
       FD_SET(tuberia2_fd, &rfds);

       /* Wait for an indefinite amount of time. */
       tv.tv_sec = 5;
       tv.tv_usec = 0;

       int fd_max = (tuberia1_fd > tuberia2_fd) ? tuberia1_fd : tuberia2_fd;

       retval = select(fd_max, &rfds, NULL, NULL, &tv);
       /* Don't rely on the value of tv now! */

       if (retval == -1)
           perror("select()");
           exit(EXIT_FAILURE);

       if(FD_ISSET(tuberia1_fd, &rfds)){
           n_read = read(tuberia1_fd, &buf, BUF_SIZE);
           if (n_read == 0){
               close(tuberia1_fd);
               tuberia1_fd = open("tuberia1", O_RDONLY);
           }else{
               buf[n_read] = '\0';
               printf("tuberia1: %s", buf);
           }
       } else if (FD_ISSET(tuberia2_fd, &rfds)){
           n_read = read(tuberia2_fd, &buf, BUF_SIZE);
           if (n_read == 0){
               close(tuberia2_fd);
               tuberia2_fd = open("tuberia2", O_RDONLY);
           }else{
               buf[n_read] = '\0';
               printf("tuberia2: %s", buf);
           }
       }
   }
}

Это все еще не работает. Запуск его под GDB показывает, что программа никогда не прогрессирует после первого open.

1 Ответ

0 голосов
/ 08 января 2019

Вам необходимо использовать FD_SET в дескрипторах файлов, которые вам действительно интересны, а именно tuberia1_fd и tuberia2_fd.

Так что-то вроде ...

while (1) {
  FD_ZERO(&rfds);
  FD_SET(tuberia1_fd, &rfds);
  FD_SET(tuberia2_fd, &rfds);
  int max;
  if (tuberia1_fd > tuberia2_fd) {
    max = tuberia1_fd;
  } else {
    max = tuberia2_fd;
  }
  tv.tv_sec = 0;
  tv.tv_usec = 0;
  retval = select(max + 1, &rfds, NULL, NULL, &tv);
...