从命名管道读取

时间:2019-01-08 19:59:39

标签: c pipe named-pipes

我必须编写一个程序来监视两个命名管道并打印通过其中一个发送的信息。

当其中一个管道的写端关闭时,程序将检测到该情况并关闭并再次打开管道。

这是我到目前为止写的:

#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 :(得分:1)

您需要在您真正感兴趣的文件描述符上使用FD_SET,即tuberia1_fdtuberia2_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);