系统编程-进程-先后fork或open一个文件的区别
关联博文:
当文件操作遇上fork
Linux内核的文件结构体
struct file {
.........
struct path f_path; //文件的路径
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations *f_op;//访问方式
atomic_long_t f_count; //文件的引用计数,引用计数值为0时,文件才会关闭
unsigned int f_flags; //标志位
mode_t f_mode; //读写等权限
loff_t f_pos; //读到了哪个位置
struct fown_struct f_owner;
unsigned int f_uid, f_gid; //文件所属uid,gid
struct file_ra_state f_ra;
u64 f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
/* needed for tty driver, and maybe others */
void *private_data;
.............
};
文件的引用计数,引用计数值为0时,文件才会被关闭。
两种情景分析:
1.fork()之前就open了文件,并且读取了部分内容
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h> int main()
{
int fd = open("tmp.txt",O_RDONLY);
assert(fd!=-1); char buff[10]={0}; pid_t pid = fork(); if(pid == 0){
read(fd,buff,1); //子进程读1个字节内容
printf("buff = %s\n",buff); }else if(pid > 0){
sleep(5); //保证子进程可以先读文件
read(fd,buff,2); //父进程读2个字节
printf("buff = %s\n",buff);
wait(NULL); //收尸,不获取死因
} close(fd);
return 0;
}

tmp.txt的内容为“niceday”
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# gcc process.c -o ab
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process#
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# ./ab
buff = n
buff = ic
小结:
先open再fork,文件只被打开一次,父子进程共享一个文件描述信息,包括引用计数、读取位置等等。
虽然父子进程都读取了该文件,由于文件的引用计数始终为1,所以只需要close一次即可。
可以在子进程代码分支中close,也可以在父进程代码分支close,还可以在公共部分close。
子进程复制了父进程的文件表项指针, 指向的是同一个文件表项,如下图:

2.fork()调用之后open文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h> int main()
{
pid_t pid = fork(); int fd = open("tmp.txt",O_RDONLY);
assert(fd!=-1); char buff[10]={0}; if(pid == 0){
read(fd,buff,1); //子进程读1个字节内容
printf("buff = %s\n",buff); }else if(pid > 0){
sleep(5); //保证子进程可以先读文件
read(fd,buff,2); //父进程读2个字节
printf("buff = %s\n",buff);
wait(NULL); //收尸,不获取死因
} close(fd);
return 0;
}
tmp.txt的内容为“niceday”, 同上。
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# gcc process.c -o ab
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process#
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# ./ab
buff = n
buff = ni
小结:
此时的文件描述信息不再是共享的,一个文件被打开了两次,即引用计数值为2,每个进程都有自己的一份,所以两个进程读写操作互不影响。

总结:
先open,再fork:子进程无条件继承父进程的文件描述信息,子进程和父进程指向同一个文件描述信息。
先fork,再open:子进程有自己的配置,和父进程的配置是相互独立的关系。所谓配置,例如文件描述信息。
文末,再来一幅图(不一样的精彩)

.
系统编程-进程-先后fork或open一个文件的区别的更多相关文章
- Linux系统编程@进程通信(一)
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
- linux服务器开发二(系统编程)--进程相关
进程相关的概念 程序与进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(CPU.内存.打开的文件.设备.锁等等). 进程,是一个抽象的概念,与操作系统原理联系紧密.进程是活跃的程序,占用系 ...
- linux系统编程-进程
进程 现实生活中 在很多的场景中的事情都是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的: 如下是一段视频,迈克杰克逊的一段视频: http://v.youku.com ...
- (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹
原文 (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) Windows Shell 编程,即 Windows ...
- Linux系统编程@进程管理(一)
课程目标: 构建一个基于主机系统的多客户即时通信/聊天室项目 涉及的理论知识 进程控制:僵尸进程/孤儿进程.进程控制.守护进程... 进程间通信:管道.命名管道.信号... 多线程编程: 锁.信号量. ...
- Linux系统编程@进程管理(二)
1.创建守护进程(Deamon) 守护进程的概念与作用 后台服务程序 – 系统服务,进程名字往往以’d’结尾,生存周期比较长(系统装入时启动,关闭时候终止.系统装入两种启动方式:1从启动脚本.etc/ ...
- [linux] C语言Linux系统编程进程基本概念
1.如果说文件是unix系统最重要的抽象概念,那么进程仅次于文件.进程是执行中的目标代码:活动的.生存的.运行的程序. 除了目标代码进程还包含数据.资源.状态以及虚拟化的计算机. 2.进程体系: 每一 ...
- 《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)
<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候 ...
- (C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹
1 - 基础,浏览一个文件夹 我们知道,在win32中是以外壳名字空间的形式来组织文件系统的,在外壳名字空间里的每一个对象(注)都实现了一个IShellFolder的接口,通过这个接口我们可以直接查询 ...
- Linux系统编程-----进程fork()
在开始之前,我们先来了解一些基本的概念: 1. 程序, 没有在运行的可执行文件 进程, 运行中的程序 2. 进程调度的方法: 按时间片轮转 先来先服务 短时间优先 按优先级别 3. 进程的状态: 就绪 ...
随机推荐
- Packer构建openStack镜像
目录 使用Packer自动化构建镜像 使用Packer自动化构建镜像 openstack插件安装:OpenStack | Integrations | Packer | HashiCorp Devel ...
- Django 不通过外键实现多表关联查询
Django不通过外键实现多表关联查询 by:授客 QQ:1033553122 测试环境 Win 10 Python 3.5.4 Django-2.0.13.tar.gz 需求 不通过外键,使 ...
- 面试题-python 什么是闭包(closure)?
前言 前面学了装饰器,那么闭包和装饰器有什么区别呢?闭包传递的是变量,而装饰器传递的是函数对象,只是传的参数内容不一样,闭包的概念包含了装饰器,可以说装饰器是闭包的一种,它只是传递函数对象的闭包. 先 ...
- MSPM0G3507外设DMA学习笔记
概述 变量的存储 正常情况下,变量存储在SRAM中,如果要发送该变量的值到外设,需要调用内核操作,使SRAM中的数据送到外设. 此类型操作过多会导致占用CPU高,整体卡顿. DMA控制概述 DMA:D ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-57- 上传文件 - 番外篇
1.简介 前边的三篇文章基本上对文件上传的知识介绍和讲解的差不多了,今天主要是来分享宏哥在文件上传的实际操作中发现的一个问题:input控件和非input控件的上传API对其都可以上传成功.废话不多说 ...
- ArcGIS for Android入门(Java):初体验
准备工作 开发工具:Android Studio 环境:jdk 11 (首次接触安卓开发,可能有的地方不太对,还请给位大佬多多指点) 项目搭建 打开Android Studio,点击New Proje ...
- 【Java】讲讲StreamAPI
预设场景: 从Mybatis调用Mapper得到的用户集合 List<UserDTO> userList = new ArrayList<>(); 常用的几种API用法示例: ...
- Implementation of Reinforcement Learning with Meta-Critic Networks and GAE in a Human-Centered Framework
论文<Future of AI and Empowering Reinforcement Learning with Meta-Critic Networks and GAE in a Huma ...
- Ubuntu18.04系统下网络文件系统nfs的安装及简单配置
硬件环境: 两台Ubuntu18.04服务器使用局域网连接,IP分别为192.168.11.66 和 192.168.11.206. ================================= ...
- 华为高性能计算(HPC)文档——技术支持>智能计算解决方案>高性能计算>HPC
链接地址: https://support.huawei.com/enterprise/zh/server-solutions/hpc-pid-253585671 ================== ...