美文网首页分布式架构
fork之前的缓冲区问题

fork之前的缓冲区问题

作者: perryn | 来源:发表于2019-06-11 14:22 被阅读0次

fork 系统调用

Description

  • fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process

代码例子

/*************************************************************************
  > File Name: fork0.c
  > Author:perrynzhou 
  > Mail:perrynzhou@gmail.com 
  > Created Time: Tue 11 Jun 2019 10:27:20 AM CST
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
void usage(char *s)
{
  printf("%s -f {0 | 1}\n", s);
  printf("   1  -- force flush all opened stream before fork\n");
  printf("   0  -- not flush all opened stream before fork\n");
}
bool is_number(const char *s)
{
  if (s == NULL)
  {
    return false;
  }
  while (*s != '\0')
  {
    if (isdigit(*s++) == 0)
    {
      return false;
    }
  }
  return true;
}
int main(int argc, char *argv[])
{
  if (argc != 3)
  {
    usage(argv[0]);
    exit(0);
  }
  const char *cmd_parse_fmt = "f:";
  char ch;
  int force_flush_flag = 0;
  while ((ch = getopt(argc, argv, cmd_parse_fmt)) != -1)
  {
    switch (ch)
    {
    case 'f':
      if (!is_number(optarg))
      {
        force_flush_flag = -1;
      }
      else
      {
        force_flush_flag = atoi(optarg);
      }
      break;
    default:
      break;
    }
  }
  if (force_flush_flag > 1 || force_flush_flag < 0)
  {
    usage(argv[0]);
    exit(0);
  }
  printf("flush opened stream :%d\n", force_flush_flag);

  printf("[%ld]begin\n", getpid());
  pid_t pid;
  if (force_flush_flag == 1)
  {
    fflush(NULL);
  }
  if ((pid = fork()) < 0)
  {
    perror("fork");
    exit(0);
  }
  else if (pid == 0)
  {
    printf("[%ld] child process working\n", getpid());
    exit(0);
  }
  else
  {
    printf("[%ld] parent process working\n", getpid());
  }
  return 0;
}

标准输出

image.png
  • 标准输出 红色标记的都是输出一个。

文件输出

image.png
  • 文件输出 f=1和f=0 结果完全不同,这是为什么?

标准输出和文件输出

  • 标准输入输出是行缓冲模式(\n,强制输出),在终端执行fork之前的printf,都是执行一次。
  • 文件输入输出是全缓冲模式(buffer到了指定的size,才会输出)
  • 当执行 test_fork -f 0重定向文件 时候,父进程执行fork之后,父子进程的地址空间是cow,没有任何改动的前提下,都是执行同一个地址空间。此时,父子进程执行的缓冲区都是一模一样,所以可以看到父子进程都会执行fork之前的printf.所以文件看到的是2个"flush opened stream :0"和"[92741]begin".
  • 当f=1,重定向文件时候可以看到,父子进程仅仅执行一次 "flush opened stream :1"和"[92741]begin".原因在于f=1的时候会在父进程fork之前执行fflush(NULL),此时执行这个函数目的在于强制flush所有的已经打开的stream.

相关文章

  • fork之前的缓冲区问题

    fork 系统调用 Description fork() creates a new process by ...

  • OpenGL ES 3.0(六)缓冲区对象、PBO、FBO

    缓冲区对象 创建: 绑定: 缓冲区对象的绑定点有: 删除: 填充缓冲区: 在使用 glBufferData 之前,...

  • 问题:Fork/Join框架是什么

    问题 Fork/Join框架是什么 答案 Fork/Join框架 Fork/Join框架提供了工具通过利用所有可用...

  • QT+OPenGL十六之模板缓冲区

    模板缓冲区(Stencil Buffer) 模板缓冲区的作用是可以自定义丢弃片段。作用在深度缓冲区之前,被保留的片...

  • node缓冲区解读

    缓冲区解读 我们主要聊聊以下几个方面的问题: 什么是缓冲区,用来做啥 如何创建缓冲区 访问缓冲区 设置某个字节的数...

  • 操作系统-进程通信

    LINUX的六大通行方式: 管道:匿名管道:在内核中申请一块固定大小的缓冲区,程序具有读写权限,一般使用fork函...

  • 02 线程的并发工具类

    1 Fork-Join 1.1 Fork/Join 体现了“分而治之” 什么是分而治之?规模为N的问题,N<阈值,...

  • 如何优雅的修改项目中node_modules源码

    fork方式 流程 github上fork此代码 修正问题 提交pull request (可省略,但是有必要) ...

  • 知识总结:I/O模型基础

    I/O基础 1、java1.4之前,java对I/O支持不完善,存在以下问题: 没有数据缓冲区,I/O性能存在问题...

  • golang项目fork的问题

    问题 4月份换了一份工作,新工作是使用golang开发。当我在代码仓库中fork了一份代码准备在自己的repo中开...

网友评论

    本文标题:fork之前的缓冲区问题

    本文链接:https://www.haomeiwen.com/subject/qpaffctx.html