问:从管道到屏幕读取

时间:2015-11-11 18:57:18

标签: 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;
  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));

     }
  }
}

问题是它没有真正从文件中读取内容。我试过发送一串字符而不是从文件中读取它并按预期工作,两个孩子都打印了一次消息并且程序结束了。

有什么想法吗?阅读完手册后,我仍然无法看到问题所在。

3 个答案:

答案 0 :(得分:3)

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

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

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

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

正在读取指向文件的指针 - 不是非常有用: - )

答案 1 :(得分:1)

这里有几个问题:

  1. 您通过传递read &fd来使用FILE*功能。这个函数需要一个指向要打印的“缓冲区”的指针,我想这里buf
  2. 你不检查错误。例如,如果fopen失败。
  3. 您永远不会从您的文件中读取数据,因此您无需向儿童发送任何内容。
  4. 您必须获得read(在儿童中)的返回值,因为它是您获得的有效数据量。因此,在此之后您必须打印的数据量(到标准输出)。
  5. 所以这是一个示例代码,请参阅内部的评论:

    // 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"
    }
    

    在不需要或结束时,您必须关闭管道的每个部分。在文件描述符打开之前,读取将阻止该过程。仅当最后一个写入对应关闭时,读取返回&lt; = 0。

    注意:1。正确使用读/写功能2.检查错误3.从文件读取并写入管道4.处理读取的有效数据量(ret变量)这样你就可以编写(“屏幕”或其他文件描述符适当的数据。

答案 2 :(得分:0)

据我所知,你没有读到任何关于buf的内容。