简体   繁体   English

没有fflush(stdout)的父进程中没有output

[英]No output in the parent process without fflush(stdout)

I'm trying to understand what is behind this behaviour in my parent process.我试图了解父进程中此行为背后的原因。

Basically, I create a child process and connect its stdout to my pipe. The parent process continuously reads from the pipe and does some stuff.基本上,我创建了一个子进程并将其标准输出连接到我的 pipe。父进程不断地从 pipe 读取数据并做一些事情。

I noticed that when inserting the while loop in the parent the stdout seems to be lost, nothing appears on the terminal etc I thought that the output of stdout would somehow go to the pipe (maybe an issue with dup2) but that doesn't seem to be the issue.我注意到当在父级中插入 while 循环时,stdout 似乎丢失了,终端上什么也没有出现等我认为 stdout 的 output 会以某种方式从 go 到 pipe(可能是 dup2 的问题),但这似乎不是成为问题。 If I don't continuously fflush(stdout) in the parent process, whatever I'm trying to get to the terminal just won't show.如果我不在父进程中连续fflush(stdout) ,无论我试图到达终端的是什么,都不会显示。 Without a while loop in the parent it works fine, but I'm really not sure why it's happening or if the rest of my implementation is problematic somehow.如果父级中没有 while 循环,它工作正常,但我真的不确定为什么会发生,或者我的实现的 rest 是否有问题。

Nothing past the read system call seems to be going to the stdout in the parent process.读取系统调用之后的任何内容似乎都不会进入父进程中的标准输出。 Assuming the output of inotifywait in the pipe is small enough ( 30 > bytes ), what exactly is wrong with this program?假设 pipe 中 inotifywait 的 output 足够小( 30 > bytes ),这个程序究竟有什么问题?

What I expect to happen is the stdout of inotifywait to go to the pipe, then for the parent to read the message, run strtok and print the file name (which only appears in stdout when I fflush)我期望发生的是 inotifywait 的 stdout 到 go 到 pipe,然后让父级读取消息,运行 strtok 并打印文件名(它只在我 fflush 时出现在 stdout 中)

Running the program with inotify installed and creating any file in the current directory of the program should be enough.在安装了 inotify 的情况下运行程序并在程序的当前目录中创建任何文件就足够了。 Removing the while loop does print the created file's name (as expected).删除 while 循环确实会打印创建的文件的名称(如预期的那样)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
int main(void) {
  char b[100];
  int pipefd;
  if (mkfifo("fifo", 0666) == -1) {
    if (errno != EEXIST) {
      perror("mkfifo");
      exit(EXIT_FAILURE);
    }
  }

  pid_t pid = fork();
  if (pid < 0) {
    perror("fork");
    exit(1);
  }

  if ((pipefd = open("fifo", O_RDWR)) < 0) {
    perror("open pipe");
    exit(EXIT_FAILURE);
  }

  if (pid == 0) {
    dup2(pipefd, 1);
    const char* dir = ".";
    const char* args[] = {"inotifywait", dir,  "-m",       "-e",
                          "create",      "-e", "moved_to", NULL};
    execvp("inotifywait", (char**)args);
    perror("inotifywait");
  } else {
    while (1) {
      fflush(stdout);  // the output only appears in stdout with this here
      if (read(pipefd, b, 30) < 0) {
        perror("problem @ read");
        exit(1);
      }
      char filename[30];
      printf("anything");
      sscanf(b, "./ CREATE %s", filename);
      printf("%s", filename);
    }
  }
}

The streams used by the C standard library are designed in such a way that they are normally buffered (except for the standard error stream stderr ). C 标准库使用的流的设计方式通常是缓冲的(标准错误 stream stderr除外)。

The standard output stream is normally line buffered, unless the output device is not an interactive device, in which case it is normally fully buffered.标准 output stream 通常是行缓冲的,除非 output 设备不是交互式设备,在这种情况下它通常是完全缓冲的。 Therefore, in your case, it is probably line buffered.因此,在您的情况下,它可能是行缓冲的。

This means that the buffer will only be flushed这意味着缓冲区只会被刷新

  1. when it is full,当它满了,
  2. when an \n character is encountered,当遇到\n字符时,
  3. when the stream is closed (eg during normal program termination),当 stream 关闭时(例如在正常程序终止期间),
  4. when reading input from an unbuffered or line-buffered stream (in certain situations), or从无缓冲或行缓冲的 stream 读取输入时(在某些情况下),或
  5. when you explicitly call fflush .当您显式调用fflush时。

This explains why you are not seeing the output, because none of the above are happening in your infinite loop (when you don't call fflush ).这解释了为什么您没有看到 output,因为以上都没有发生在您的无限循环中(当您不调用fflush时)。 Although you are reading input, you are not doing this from a C standard library FILE * stream. Instead, you are bypassing the C runtime library (eg glibc) by using the read system call directly (ie you are using a file descriptor instead of a stream).尽管您正在读取输入,但您并不是从 C 标准库FILE * stream 执行此操作。相反,您通过直接使用read系统调用来绕过 C 运行时库(例如 glibc)(即您正在使用文件描述符而不是流)。

The simplest solution to your problem would probably be to replace the line解决您的问题的最简单方法可能是更换线路

printf("%s", filename);

with:和:

printf("%s\n", filename);

If stdout is line-buffered (which should be the case if it is connected to a terminal), then the input should automatically be flushed after every line and an explicit call to fflush should no longer be necessary.如果stdout是行缓冲的(如果它连接到终端就应该是这种情况),那么输入应该在每一行之后自动刷新并且不再需要显式调用fflush

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM