C Q:从管道到屏幕的读数

C Q:从管道到屏幕的读数,c,file,pipe,C,File,Pipe,我正试图编写一个程序,从文件中读取一些文本并将其打印到屏幕上。父级将读取文件内容并将其写入n个管道,子级将读取并打印 到目前为止,我得到的是: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> int main (void) { pid_t pid; char c; FI

我正试图编写一个程序,从文件中读取一些文本并将其打印到屏幕上。父级将读取文件内容并将其写入n个管道,子级将读取并打印

到目前为止,我得到的是:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>

int main (void)
{
  pid_t pid;
  char c;
  FILE *fd;
  char buf[100];
  int N_CHILDREN = 2;
  int p[N_CHILDREN][2];
  int i,j;

  for(i=0; i<N_CHILDREN; i++)
  {
    pipe(p[i]);
  }

  fd=fopen("123.txt","r");

  for(j=0; j < N_CHILDREN;j++)
  { 
    pid = fork ();

    if (pid == 0)
     {     
           close (p[j][1]);
           while(read(p[j][0], &fd,sizeof(buf)) > 0)
            printf("\n%c",&fd);

      }
    if (pid < 0) 
     {
       //Fork Failed
           fprintf (stderr, "Fork failure.\n");
           return EXIT_FAILURE;
         }
    if ( pid > 0) //Parent
     {  
             close (p[j][0]);
             write(p[j][1], fd ,sizeof(buf));

     }
  }
}
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
pid_t pid;
字符c;
文件*fd;
char-buf[100];
int N_CHILDREN=2;
int p[N_CHILDREN][2];
int i,j;
对于(i=0;i=0)
printf(“\n%c”,&fd);
}
if(pid<0)
{
//Fork失败了
fprintf(stderr,“Fork failure.\n”);
返回退出失败;
}
如果(pid>0)//父级
{  
收盘(p[j][0]);
写入(p[j][1],fd,sizeof(buf));
}
}
}
问题是它并没有真正从文件中读取内容。我试着给它发送一个字符串,而不是从一个文件中读取,结果一切正常,两个孩子只打印了一次消息,程序就结束了


有什么想法吗?阅读这些手册后,我仍然看不出问题出在哪里。

据我所知,您没有读入buf。

据我所知,您没有读入buf。

您混淆了C标准I/O流(使用
fopen()
;使用
fprintf()编写)
等,使用
fscanf()
等)读取Unix文件描述符I/O(使用
open()
pipe()
等创建,使用
write()
等写入,使用
read()
等读取。)

标准I/O函数将不透明的
文件*
作为句柄;Unix I/O函数将文件描述符(小int)作为句柄

一旦你理解了概念上的差异,我相信你会意识到这一点

FILE *fd = ...
read(..., &fd, ...);

正在读取指向文件的指针-)

您将C标准I/O流(使用
fopen()
创建;使用
fprintf()
等写入;使用
fscanf()
等读取)与Unix文件描述符I/O(使用
open()
pipe()创建)相混淆
等,使用
write()写入(
等,使用
read()读取(
等)

标准I/O函数将不透明的
文件*
作为句柄;Unix I/O函数将文件描述符(小int)作为句柄

一旦你理解了概念上的差异,我相信你会意识到这一点

FILE *fd = ...
read(..., &fd, ...);
正在读取指向文件的指针--不是非常有用:-)

这里有几个问题:

  • 通过传递
    &fd
    ,这是一个
    文件*
    ,您错误地使用了
    read
    函数。这个函数需要一个指向“缓冲区”的指针来打印,我猜这里是
    buf
  • 您不检查错误。例如,如果
    fopen
    失败
  • 您从未从文件中读取数据,因此“没有”可发送给孩子
  • 您必须获得
    read
    (在子项中)的返回值,因为它是您获得的有效数据量。因此,这是之后必须打印的数据量(到标准输出)
  • 下面是一个示例代码,请参见下面的注释:

    // put here all the needed includes (see manpages of functions)
    
    // it is better to create a function for the child: the code
    // is easier to read
    // the child just get the file descriptor to read (the pipe)
    void child(int fd) {
      char buf[100];  // buffer to store data read
      int ret;        // the number of bytes that are read
    
      // we read from 'fd', into 'buf'. It returns the number of bytes
      // really read (could be smaller than size). Return <=0 when over
      while((ret = read(fd, buf, sizeof(buf))) > 0) {
        // write the 'ret' bytes to STDOUT (which as file descriptor 1)
        write(1, buf, ret);
      }
    }
    
    int main (void) {
      pid_t pid;
      char buf[100];
      int N_CHILDREN = 2;
      int p[N_CHILDREN][2];
      int i,j, ret;
      int fdi;
      // create the pipes
      for(i=0; i<N_CHILDREN; i++) {
        if (pipe(p[i]) == -1) {
          perror("pipe");  // ALWAYS check for errors
          exit(1);
        }
      }
      // open the file (with 'open' not 'fopen', more suitable for
      // reading raw data
      fdi = open("123.txt",O_RDONLY);
      if (fdi < 0) {
        perror("open"); // ALWAYS check for errors
        exit(1);
      }
      // just spawn the children
      for(j=0; j < N_CHILDREN;j++) { 
        pid = fork();
        if (pid < 0) {
          perror("fork"); // ALWAYS check for errors
          exit(1);
        }
        if (pid == 0) {  // child
          close(p[j][1]);  // close the writing part
          child(p[j][0]);  // call child function with corresp. FD
          exit(0);  // leave : the child should do nothing else
        }
      }
      // don't need that part
      for(j=0; j<N_CHILDREN; j++) {
        close(p[j][0]);  // close the read-part of pipes
      }
      // need to read file content, see comment in child() function
      while ((ret = read(fdi, buf, sizeof(buf))) > 0) {
        // write the data to all children
        for(j=0; j<N_CHILDREN; j++) {
          write(p[j][1], buf , ret); // we write the size we get
        }
      }
      // close everithing
      for(j=0; j<N_CHILDREN; j++) {
        close(p[j][1]);  // needed, see text after
      }
      close(fdi); // close read file
      return(0); // main returns a int, 0 is "ok"
    }
    
    //将所有需要的内容放在这里(参见函数手册)
    //最好为孩子创建一个函数:代码
    //更容易阅读
    //子级只获取要读取的文件描述符(管道)
    无效子项(int-fd){
    char buf[100];//用于存储读取数据的缓冲区
    int ret;//读取的字节数
    //我们从'fd'读入'buf'。它返回字节数
    //真正读取(可能小于大小)。返回0){
    //将'ret'字节写入STDOUT(作为文件描述符1)
    写入(1,buf,ret);
    }
    }
    内部主(空){
    pid_t pid;
    char-buf[100];
    int N_CHILDREN=2;
    int p[N_CHILDREN][2];
    int i,j,ret;
    国际直接投资;
    //创建管道
    对于(i=0;i这里的几个问题:

  • 您通过传递
    &fd
    (这是一个
    文件*
    )错误地使用了
    读取
    函数。这个函数需要一个指向“缓冲区”的指针来打印,我猜这里是
    buf
  • 您不检查错误。例如,如果
    fopen
    失败
  • 您从未从文件中读取数据,因此“没有”可发送给孩子
  • 您必须获得
    read
    (在子项中)的返回值,因为它是您获得的有效数据量。因此,它是在此之后您必须打印的数据量(到标准输出)
  • 下面是一个示例代码,请参见下面的注释:

    // put here all the needed includes (see manpages of functions)
    
    // it is better to create a function for the child: the code
    // is easier to read
    // the child just get the file descriptor to read (the pipe)
    void child(int fd) {
      char buf[100];  // buffer to store data read
      int ret;        // the number of bytes that are read
    
      // we read from 'fd', into 'buf'. It returns the number of bytes
      // really read (could be smaller than size). Return <=0 when over
      while((ret = read(fd, buf, sizeof(buf))) > 0) {
        // write the 'ret' bytes to STDOUT (which as file descriptor 1)
        write(1, buf, ret);
      }
    }
    
    int main (void) {
      pid_t pid;
      char buf[100];
      int N_CHILDREN = 2;
      int p[N_CHILDREN][2];
      int i,j, ret;
      int fdi;
      // create the pipes
      for(i=0; i<N_CHILDREN; i++) {
        if (pipe(p[i]) == -1) {
          perror("pipe");  // ALWAYS check for errors
          exit(1);
        }
      }
      // open the file (with 'open' not 'fopen', more suitable for
      // reading raw data
      fdi = open("123.txt",O_RDONLY);
      if (fdi < 0) {
        perror("open"); // ALWAYS check for errors
        exit(1);
      }
      // just spawn the children
      for(j=0; j < N_CHILDREN;j++) { 
        pid = fork();
        if (pid < 0) {
          perror("fork"); // ALWAYS check for errors
          exit(1);
        }
        if (pid == 0) {  // child
          close(p[j][1]);  // close the writing part
          child(p[j][0]);  // call child function with corresp. FD
          exit(0);  // leave : the child should do nothing else
        }
      }
      // don't need that part
      for(j=0; j<N_CHILDREN; j++) {
        close(p[j][0]);  // close the read-part of pipes
      }
      // need to read file content, see comment in child() function
      while ((ret = read(fdi, buf, sizeof(buf))) > 0) {
        // write the data to all children
        for(j=0; j<N_CHILDREN; j++) {
          write(p[j][1], buf , ret); // we write the size we get
        }
      }
      // close everithing
      for(j=0; j<N_CHILDREN; j++) {
        close(p[j][1]);  // needed, see text after
      }
      close(fdi); // close read file
      return(0); // main returns a int, 0 is "ok"
    }
    
    //将所有需要的内容放在这里(参见函数手册)
    //最好为孩子创建一个函数:代码
    //更容易阅读
    //子级只获取要读取的文件描述符(管道)
    无效子项(int-fd){
    char buf[100];//用于存储读取数据的缓冲区
    int ret;//读取的字节数
    //我们从'fd'读入'buf'。它返回字节数
    //真正读取(可能小于大小)。返回0){
    //将'ret'字节写入STDOUT(作为文件描述符1)
    写入(1,buf,ret);
    }
    }
    内部主(空){
    pid_t pid;
    char-buf[100];
    int N_CHILDREN=2;
    int p[N_CHILDREN][2];
    int i,j,ret;
    国际直接投资;
    //创建管道
    
    对于(i=0;i
    read(p[j][0],&fd,sizeof(buf))
    fd
    是一个
    文件*
    ,您可能指的是
    buf
    ?之后,您不能将“缓冲区”打印为“%c”。注意:编译时总是带有所有警告,您会看到几个问题(不是全部,而是几个)。至少您会看到,
    read
    是用
    &fd
    调用的,这是错误的。
    read(p[j][0],&fd,sizeof(buf))
    fd
    是一个
    文件*
    ,您可能是指
    buf
    ?之后,您不能将“缓冲区”打印为“%c”。注意:始终使用所有警告进行编译,您会看到一些问题(不是全部,但有几个)。至少你会看到
    阅读