同时读取命名和未命名管道的问题

Problem with reading from named and unnamed pipes at the same time

我正在尝试让一个进程同时从命名管道和一些未命名管道中读取数据。首先我有一个主进程,它创建一个子进程,然后初始化一个命名管道,等待来自终端的数据发送到命名管道:

    int main(){
  signal(SIGINT, sigint);

  if(fork()==0){
    newProcess();
    exit(0);
  }



  unlink(PIPE_NAME);

  printf("Creating named pipe.\n");
  if ((mkfifo(PIPE_NAME, O_CREAT|O_EXCL|0600)<0) && (errno!= EEXIST)) {
    perror("Cannot create pipe: ");
    exit(0);
  }
  printf("Named pipe created.\n");


  int named_pipe_fd;
  printf("Opening named pipe.\n");
  if ((named_pipe_fd = open(PIPE_NAME, O_WRONLY)) < 0) {
    perror("Cannot open pipe for writing: ");
    exit(0);
  }
  printf("Named pipe open.\n");


  char toSend[512];
  //Sends data via the NAMED pipe to our child process
  while(1){
    scanf("%[^\n]%*c", toSend);
    printf("[RaceSimulator] Sending (%s)\n",toSend);
    write(named_pipe_fd, toSend, sizeof(toSend));
  }


  return 0;
}

子进程将命名管道打开为读取模式,并创建一个充满文件描述符的数组,等待信息到达。现在我还没有创建未命名的管道,所以它们在数组中的值为 -1:

void newProcess(){


  //Initialize the pipes
  for(int i=0;i<MAX;i++){
    pipes[i]=-1;
  }

  //OPEN NAMED PIPE FOR READING
  int fd;
  if ((fd= open(PIPE_NAME, O_RDONLY)) < 0) {
    perror("Cannot open pipe for reading: ");
    exit(0);
  }


  pipes[0]=fd;
  char received[512];

  //Loop that waits for data to appear in the pipes
  while(1){

    fd_set read_set;
    FD_ZERO(&read_set);

    for (int channel=0;channel<MAX;channel++) {
      FD_SET(pipes[channel], &read_set);
    }

    if (select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL) > 0 ) {

       if (FD_ISSET(pipes[0], &read_set)) {

          read(pipes[0],received,sizeof(received));
          printf("[Named pipe] Received %s.\n",received);

      }

      //Unamed pipes are still not created!
      for (int channel=1;channel<MAX;channel++) {

        if (FD_ISSET(pipes[channel], &read_set)) {

          read(pipes[channel],received,sizeof(received));
          printf("[Unamed pipe] Received %s.\n",received);

        }
      }
    }
  }
}

问题是,当我在终端上写入时,终端只回写主进程的printf。这意味着没有任何东西被发送到命名管道的另一端,但我不明白为什么。这是整个代码(注意:这是一个片段,出于法律原因我不能发送原始代码,而且我知道我在这个片段中有太多包含:P):

#define PIPE_NAME "pipe"
#define MAX 5

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>


int pipes[MAX];

void clean(){
  unlink(PIPE_NAME);
}

void sigint(int signum){
  clean();
  exit(0);
}


void newProcess(){


  //Initialize the pipes
  for(int i=0;i<MAX;i++){
    pipes[i]=-1;
  }

  //OPEN NAMED PIPE FOR READING
  int fd;
  if ((fd= open(PIPE_NAME, O_RDONLY)) < 0) {
    perror("Cannot open pipe for reading: ");
    exit(0);
  }


  pipes[0]=fd;
  char received[512];

  //Loop that waits for data to appear in the pipes
  while(1){

    fd_set read_set;
    FD_ZERO(&read_set);

    for (int channel=0;channel<MAX;channel++) {
      FD_SET(pipes[channel], &read_set);
    }

    if (select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL) > 0 ) {

       if (FD_ISSET(pipes[0], &read_set)) {

          read(pipes[0],received,sizeof(received));
          printf("[Named pipe] Received %s.\n",received);

      }

      //Unamed pipes are still not created!
      for (int channel=1;channel<MAX;channel++) {

        if (FD_ISSET(pipes[channel], &read_set)) {

          read(pipes[channel],received,sizeof(received));
          printf("[Unamed pipe] Received %s.\n",received);

        }
      }
    }
  }
}


int main(){
  signal(SIGINT, sigint);

  if(fork()==0){
    newProcess();
    exit(0);
  }



  unlink(PIPE_NAME);

  printf("Creating named pipe.\n");
  if ((mkfifo(PIPE_NAME, O_CREAT|O_EXCL|0600)<0) && (errno!= EEXIST)) {
    perror("Cannot create pipe: ");
    exit(0);
  }
  printf("Named pipe created.\n");


  int named_pipe_fd;
  printf("Opening named pipe.\n");
  if ((named_pipe_fd = open(PIPE_NAME, O_WRONLY)) < 0) {
    perror("Cannot open pipe for writing: ");
    exit(0);
  }
  printf("Named pipe open.\n");


  char toSend[512];
  //Sends data via the NAMED pipe to our child process
  while(1){
    scanf("%[^\n]%*c", toSend);
    printf("[RaceSimulator] Sending (%s)\n",toSend);
    write(named_pipe_fd, toSend, sizeof(toSend));
  }


  return 0;
}

如有任何帮助,我们将不胜感激!

select 的第一个参数应该是集合中编号最大的文件描述符。由于您已将它们全部初始化为 -1,除了第 0 个,此调用:

select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL)

将不起作用。您需要将其更改为:

select(fd+1, &read_set, NULL, NULL, NULL)

或者,一旦你创建了其他的,就在其中最高的。