【问题标题】:Using pipe() and fork() to read from a file and output to the console/new file使用 pipe() 和 fork() 从文件中读取并输出到控制台/新文件
【发布时间】:2017-10-11 19:59:20
【问题描述】:

我正在尝试学习如何使用 pipe() 和 fork() 系统调用。我正在使用管道和叉子创建父进程和子进程,其中子进程将从文本文件中读取一个字符,然后通过管道将其发送到父进程,然后父进程会将字符输出到控制台,并获得所需的结果它会将整个文本打印到控制台。稍后我将对文件进行一些文本处理,子进程读取和处理,然后将更新的文本发送给父进程,但现在我只想确保我得到 pipe() 的基础知识是正确的。

示例文件:

This is a test file; it is 1 of many.
Others will follow. 

相关代码:

  pid = fork();

  ifstream fin;
  fin.open(inputFilename);
  fin.get(inputChar);

  if (pid == -1)
  {
    perror("Trouble");
    exit(2);
  }
  else if (pid == 0) //child process that reads text file and writes to parent
  {
    close(pipefds[0]);
    while(!fin.eof())
    {
      write(pipefds[1], &inputChar, sizeof(inputChar));
      fin.get(inputChar);
    }

    close(pipefds[1]);

    exit(0);
  }
  else
  {
    close(pipefds[1]);
    read(pipefds[0], readbuffer, sizeof(readbuffer));
    cout << readbuffer << endl;
    close(pipefds[0]);
    exit(0);

  }
      fin.close();

但是,当我编译和运行时,输出的长度总是不同的。有时它会打印整个文件,有时它只会打印几个字母或半行。比如。

This i

我已尝试浏览手册页并进行更多研究,但找不到任何答案。我的程序到底发生了什么,它有时会从文件中读取所有内容,但有时不会。非常感谢任何帮助!

【问题讨论】:

  • readbuffer 是如何定义的?
  • 它是一个字符数组。

标签: c++ c linux system-calls


【解决方案1】:

您似乎正试图通过一次调用read(2) 来读取管道中的所有数据。但是,与任何 I/O 操作一样,这可能总是返回比您请求的更少的字节。您应该始终检查read(2)write(2) 系统调用(和其他)的返回值,以确保它们按预期运行。

在这种情况下,您应该循环,直到您从子进程收到一些独立的通知,表明他们已完成发送数据。在这种情况下,这可以通过read(2) 返回0 发出信号,这意味着孩子关闭了管道的末端。

【讨论】:

    【解决方案2】:

    您假设父级可以通过一个read() 调用读取子级写入管道的所有内容。如果孩子通过单个 write() 调用写入所有内容,那么对于管道来说这可能是一个安全的假设,只要整体数据大小不超过管道内部缓冲区的大小。在这种情况下,当孩子通过许多小写发送数据时,这根本不安全。

    父级实际获得多少数据将部分取决于其一个read() 调用相对于子级写入的排序方式。由于这两个进程是独立的进程,并且除了管道本身之外没有使用任何 IPC,因此基本上无法预测父进程将成功读取多少数据。

    在一般情况下,必须假设读取器需要执行多次read() 调用才能读取所有发送的数据。它必须不断调用read() 并适当地处理结果数据,直到read 的返回值表明发生了I/O 错误或已到达文件末尾。请注意,文件结尾并不意味着没有更多可用的字节现在,而是不再有可用的字节永远。这发生在所有进程都关闭了管道写入端的所有副本之后。

    【讨论】:

    • 我认为无论write 调用多少次read(2) 调用都会返回所有请求的数据,我认为它永远不是一个“安全假设”制作。
    • @bnaecker,POSIX 当然不做这样的保证,但如果你愿意依赖特定实现的已知特征——在这种情况下是 Linux——那么对于那些实现,假设可以确实是安全的。然而,这不应被视为对此类做法的认可。依赖实现细节是为未来设置令人讨厌的陷阱的好方法。
    • 有趣,我不知道这是对 Linux 的保证。你怎么知道的?
    • @bnaecker,我不会说“已知特征”完全上升到“保证”的水平,但我知道这部分是因为我们目前谈话的另一方。 Linux 内核源代码当然是开放供检查以确认或反驳该命题。
    • @JohnBollinger: POSIX 确实保证PIPE_BUF字节或更少的写入行为——这样的写入是“原子的”并且永远不会与写入交错从其他来源。此外,如果管道中有可用数据,则读取永远不会返回比请求更少的数据,因此,如果您正在写入和读取固定大小的记录并且该大小为 PIPE_BUF,您也永远不会得到短读取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 2022-12-04
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    相关资源
    最近更新 更多