【问题标题】:Read from named piped从命名管道读取
【发布时间】:2019-01-08 19:59:39
【问题描述】:

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

当其中一个管道的写端关闭时,程序会检测到这一点并再次关闭和打开管道。

这是我目前所写的:

#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 &gt; 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

【问题讨论】:

  • 如果你在调试器中运行你的程序,我相当有信心你会看到执行echo 命令会导致你的程序通过第一个open(),只会阻塞第二个一。

标签: c pipe named-pipes


【解决方案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);

【讨论】:

  • 好收获!但是我已经解决了这个问题,但仍然无法正常工作
  • 您能否详细说明"does not work" 的含义?您能否在调试器中单步执行代码以找到 if 失败或出现意外情况的点?
  • 当我使用 GBD 运行它时,程序卡在第一个 open 调用上
猜你喜欢
  • 2020-07-18
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多