fork与exit、_exit的配合使用

简介:
#include "light.h"

int main(int argc, char *argv[])
{
    printf("Hello world\n");
    write(STDOUT_FILENO, "Ciao\n", 5);
    if (fork() == -1)
        errExit("fork");
    /* Both child and parent continue execution here */
    exit(EXIT_SUCCESS);
}

When we run this program with standard output directed to the terminal, we see the expected result:
$ ./fork_stdio_buf
Hello world
Ciao
However, when we redirect standard output to a file, we see the following:
$ ./fork_stdio_buf > a
$ cat a
Ciao
Hello world
Hello world


Why?
recall that the stdio buffers are maintained in a process's user-space memory.
Therefore, these buffers are duplicated in the child by fork(). When standard out-put is 
directed to a terminal, it is line-buffered by default, with the result that the newline-terminated 
string written by printf() appears immediately. However, when standard output is directed to a 
file, it is block-buffered by default. Thus, in our example, the string written by  printf() is 
still in the parent’s  stdio  buffer at the time of the fork(), and this string is duplicated in 
the child. When the parent and the child later call  exit(), they both flush their copies of the stdio 
buffers, resulting in duplicate output.

We can prevent this duplicated output from occurring in one of the following ways:
	As a specific solution to the stdio  buffering issue, we can use fflush() to flush the
stdio buffer prior to a  fork() call. Alternatively, we could use  setvbuf() or setbuf()
to disable buffering on the  stdio  stream.
	Instead of calling  exit(), the child can call  _exit(), so that it doesn’t flush stdio
buffers. This technique exemplifies a more general principle: in an application that creates 
child processes, typically on ly one of the processes (most often the parent) should terminate 
via exit(), while the other processes should terminate via _exit(). This ensures that only one 
process calls exit handlers and flushes stdio buffers, which is usually desirable.

The output of the write() in the program doesn’t appear twice, because write() transfers data 
directly to a kernel  buffer, and this buffer is not dupli-cated during a  fork(). By now, the reason 
for the second strange aspect of the program’s output when redirected to a file should be clear. 
The output of  write() appears before that from printf()  because the output of write() is immediately 
transferred to the kernel buffer cache, while the output from printf() is transferred only when 
the stdio  buffers are flushed by the call to exit().

目录
相关文章
|
10月前
|
机器学习/深度学习 人工智能 自然语言处理
MarS:微软开源金融市场模拟预测引擎,支持策略测试、风险管理和市场分析
MarS 是微软亚洲研究院推出的金融市场模拟预测引擎,基于生成型基础模型 LMM,支持无风险环境下的交易策略测试、风险管理和市场分析。
389 8
MarS:微软开源金融市场模拟预测引擎,支持策略测试、风险管理和市场分析
|
10月前
|
传感器
基于PID控制器的天线方位角位置控制系统simulink建模与仿真
本课题基于MATLAB2022a的Simulink平台,构建并仿真了天线方位角位置控制系统。通过零极点配置法整定PID控制器参数,实现对天线方位角的精确控制。系统由天线驱动装置、角度传感器、PID控制器和电机驱动电路组成,确保天线快速准确地跟踪设定方位角。PID控制器综合比例、积分、微分三个环节,优化响应速度、稳定性和准确性,适用于无线通信、雷达跟踪等领域。
|
10月前
|
存储 算法 搜索推荐
【潜意识Java】期末考试可能考的高质量大题及答案解析
Java 期末考试大题整理:设计一个学生信息管理系统,涵盖面向对象编程、集合类、文件操作、异常处理和多线程等知识点。系统功能包括添加、查询、删除、显示所有学生信息、按成绩排序及文件存储。通过本题,考生可以巩固 Java 基础知识并掌握综合应用技能。代码解析详细,适合复习备考。
159 4
|
11月前
|
JSON Dart 前端开发
鸿蒙应用开发从入门到入行 - 篇7:http网络请求
在本篇文章里,您将掌握鸿蒙开发工具DevEco的基本使用、ArkUI里的基础组件,并通过制作一个简单界面掌握使用
490 8
|
负载均衡 Linux API
CPU 隔离:实践
SUSE Labs 团队探索了 Kernel CPU 隔离及其核心组件之一:Full Dynticks(或 Nohz Full),并撰写了本系列文章。
1089 0
|
存储 数据可视化 调度
电脑的工作原理是怎样的?底层原理是什么?
电脑的工作原理是怎样的?底层原理是什么?
572 0
|
网络协议 网络安全 数据安全/隐私保护
|
机器学习/深度学习 存储 编解码
计算机视觉的基本原理
计算机视觉的基本原理
791 0
|
存储 物联网 Serverless
【文生图】可换模型,函数计算一键部署 Stable Diffusion
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。本实验答疑钉钉群:29290019867。
|
机器学习/深度学习 人工智能 算法
员工离职困扰?来看AI如何解决,基于人力资源分析的 ML 模型构建全方案 ⛵
本文通过数据科学和AI的方法,分析挖掘人力资源流失问题,构建基于机器学习的解决方案,并通过对AI模型的反向解释,深入理解导致人员流失的主要因素。
2469 1
员工离职困扰?来看AI如何解决,基于人力资源分析的 ML 模型构建全方案 ⛵