【基础IO⑧】:文件描述符fd(进程与文件的联系)
【基础IO⑧】:进程与文件之间的联系(文件描述符fd)
- 一.前言探讨[进程与文件关系]
- 二.C语言文件操作
- 三.系统文件调用
- 1.open/write
- 四.文件描述符fd
一.前言探讨[进程与文件关系]
我们首先了解一些基本的认识:
1.文件包括文件内容和文件属性
2.文件分为打开文件和没有打开文件。
3.打开的文件是谁打开的呢?又是如何打开的呢?这是我们本篇的重点处理问题。
4.没有打开的文件在哪里放着呢?
对于打开的文件我们重点想了解是谁打开的,并且是如何打开的。对于没有打开的文件我们重点想了解这些没有被打开的文件在哪里!
1.打开的文件的操作肯定是我们写代码才能操作,所以也就是我们的程序即进程!是进程打开文件。
2.对于没有打开的文件肯定很多,那这些文件是如何被分门别类的放置好的呢?这是我们要探讨的问题,因为我们想对这些未打开的文件快速的进行增删查改。
进程打开了文件,本质上就是要研究进程和文件之间的关系。
要想访问一个文件,首先需要将文件加载到内存里,并且一个进程可以打开多个文件,所以操作系统内部肯定存在很多被打开的文件!那么这些被打开的文件操作系统也需要对他们进行管理。通过先描述再组织的方式进行管理---->每一个被打开的文件操作系统都会给它创建一个文件对象,这个对象包含文件的很多属性。
所以综上:我们要想探讨一个被打开的文件,本质上是探讨进程与文件之间的关系即------->进程PCB与文件对象之间的关系。
二.C语言文件操作
C语言的常见文件操作就是fopen fwrite,fread fclose等打开文件写入文件输出文件等操作。
对于fopen(参数1,参数2)的使用很简单,就是打开某个路径下的文件,以什么样的方式打开.

所以如果不指定文件在哪个路径下,系统会默认将当前进程的路径添加上去,也就是在当前进程目录下创建。
所以如果我们将进程的当前目录修改,就可以将文件新建到别的地方了。
1.‘w’就是以写的方式打开。不过要注意w在写入之前,都会对文件进行清空操作。比如像重定向里的,打开文件但不往里面写,就会直接清空文件,说明重定向操作里面打开文件的方式就是w。
2.‘a’也是写入操作,只不过在打开文件时不会清空文件,而是直接追加在内容末尾。
3.这里还有一个问题:就是当使用fwrite时,后面计算字符串的大小需不需要+1,因为\0的原因就很困扰,为什么有时加1有时不加1呢?
首先我们要明白,字符串是C语言规定出来的,它的后面必须要有\0。但文件就不认识C语言,文件只需字符的内容就可以了,所以当我们往文件里写入时字符串时,都不需要加+1,直接计算字符串的长度即可。
还有一个知识:那就是C语言下,会默认给我们打开3个标准输入输出流:
三.系统文件调用
文件其实是在磁盘上的,磁盘又是属于硬件设备。操作系统的构成,用户层在最上面,硬件在最下面,用户要想访问硬件必须要通过操作系统,而操作系统又因为安全性只会给你提供系统调用接口来访问。
所以所有的库函数,只要要访问硬件资源,就一定要封装系统调用接口。

1.open/write

有两个open接口,这两个的区别在于第三个参数有和没有。
对于已经存在的文件,肯定有它自己的权限设置,这样才可以被访问,所以当一个文件被创建时,必须要设置这个文件的权限属性。
而第三个参数就是用来设置权限的。所以第一个open是用来打开已经存在的文件,而第二个open是用来打开创建一个没有存在的文件的,并设置这个文件的权限。我们主要用三个参数的open调用接口。
open系统调用接口的参数第一个就是文件路径,第二个参数是打开的方式,第三个参数是用过给这个文件设计权限的。返回值是int类型
open是系统调用接口,它有自己的打开文件的方式,它是采用比特位方式的标志位传递参数从而采用不同的打开方式。
O_WRONLY表示只写形式
O_CREAT表示如果文件不存在就创建
O_TRYNC表示打开文件之前先清空文件
O_APPEND表示追加,不清空。

所以C库函数fopen里封装着open系统调用函数,"w"方式就是O_WRONLY, O_CREAT, O_TRYNC三种方式组合,"a"方式就是
O_WRONLY, O_CREAT, O_APPEND三种方式组合。
fopen封装着open这个我们应该能理解,不过你没有注意到open的返回值是int类型,而fopen的返回值确实FILE类型,int类型和FILE类型之间有什么关系呢?
四.文件描述符fd
我们知道只要打开一个文件,操作系统就要给这个打开的文件创建个文件对象struct file。这个对象描述着文件许多属性。文件对象之间用链表连起来。这样操作系统对于文件的管理,就转换为对链表的增删查改了。
我们前面也说过一个进程可以打开多个文件,所以操作系统内部肯定有许多被打开的文件,那么进程是怎么知道它打开的是哪个文件呢?
其实进程PCB里存在一个指针对象,叫做struct file_struct对象。
它指向的是一个结构体对象,这个结构体里面存着一个数组struct file arr[],这个数组叫做文件描述符表,里面存的都是文件对象的地址。当进程要打开一个文件是,操作系统首先会为这个文件创建struct file对象。然后就会将这个对象地址存放在文件描述符表里。当又打开一个文件,就依次将文件对象的地址放进数组里面,最后返回该数组的下标给进程。最后调用open打开创建一个文件后,就会获得一个int类型的下标。所以本质上这个int类型的返回值就是数组的下标。也就是文件描述表的下标。而进程就是通过这个下标再次找到被打开的文件的。
所以这个下标也叫做文件描述符。本质上就是文件对象在文件描述表里位置。
所以进程是通过文件描述符fd来找到被打开的文件的。这也是为什么open返回值为什么是int类型了。
因为进程可以打开多个文件,所以这里采用的引用计数的方式进行关闭,每个文件对象都有一个计数器,当进程close这个文件时,计数器就减减,减完后如果计数器不为0,则说明还有其他进程在使用这个文件,则不真正关闭文件,当计数器为0时才真正的关闭文件。

open返回的是文件描述符fd。但fopen返回的确实FILE类型这是怎么回事呢?
其实在操作系统它只认识文件描述符fd,并不认识FILE。进程与文件之间本质是通过数组下标来联系的。
所以不管FILE是什么,它内部肯定封装着文件描述符fd。FILE其实一个结构体对象。后面我会详细介绍它。
所以对于文件操作来说,进行了两次封装,一次是函数层面的封装:库函数封装系统调用,一次是类型方面封装:FILE类型里面封装fd类型。
到这里我们就可以验证一个现象了:
你说C语言默认给我们打开了三个标准输入输出流,你怎么证明呢?
文件既然被打开了,操作系统就会给它创建结构体对象struct file。并且会将它的地址放入文件描述符表里,一开始文件描述符表里一个都没有,现在这三个放进去,应该分别对应的数组下标是 0 1 2.所以我们可以观察他们的文件描述符是什么。

相关文章:
【基础IO⑧】:文件描述符fd(进程与文件的联系)
【基础IO⑧】:进程与文件之间的联系(文件描述符fd) 一.前言探讨[进程与文件关系]二.C语言文件操作三.系统文件调用1.open/write 四.文件描述符fd 一.前言探讨[进程与文件关系] 我们首先了解一些基本的认识: 1.文件包括文件内容和文件属性 2.…...
搭建WAMP网站教程(windows+apache+mysql+php)
之前为了学习网络安全,从搭建网站学起,对网站运行有个初步的了解。 今天翻到了之前的笔记,顺手发到csdn上了。 搭建网站步骤 一、Apache 安装Apache,下载Apache之后把Apache解压,此处解压到C:\目录下 2.然后要记得安…...
瓦斯抽采VR应急救援模拟仿真系统筑牢企业安全生产防线
矿工素质对安全生产的影响很大。传统的煤矿安全事故培训出于条件差、经验少加上侥幸心理,导致其在教学内容时过于简单且不切合实际,无法真正发挥培训作用。瓦斯检查作业VR模拟实操培训通过真实还原煤矿作业环境,让受训者身临其境地进入三维仿…...
nodelist 与 HTMLCollection 的区别
原地址 https://cloud.tencent.com/developer/article/2013289 节点与元素 根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点: 整个文档是一个文档节点每个 HTML 元素是元素节点HTML 元素内的文本是文本节点每个 HTML 属性是属性节点注释是注…...
系列十二、过滤器 vs 拦截器
一、过滤器 vs 拦截器 1.1、区别 (1)触发时机不一样,过滤器是在请求进入容器后Servlet之前进行预处理的,请求结束返回也是,是在Servlet处理完后,返回给前端之前; (2)过滤…...
dockerfile运行apk命令卡住的问题解决——更换镜像
在练习docker官方文档关于docker compose初体验(https://docs.docker.com/compose/gettingstarted/)过程中,执行dockerfile命令RUN apk add --no-cache gcc musl-dev linux-headers时,出现卡住的情况,等了几千秒都不行…...
Android - 编译 openssl 踩坑之路
一、简述 如果你想快速在项目中使用上 openssl,可以使用网上其他开发者提供好的预编译库: OpenSSL(All):https://builds.viaduck.org/prebuilts/openssl/OpenSSL(3.1.*) :https://github.com/217heidai/openssl_for_android以上的预编译库可能最低只支持 API 21(即 Andro…...
verdi技巧分享--合并多个fsdb文件、统计信号边沿
文章目录 0 前言1 如何显示信号高位的02 统计信号的上升沿、下降沿3 合并信号4 将多个fsdb文件合并成一个 0 前言 分享几个这段时间学到的verdi操作 1 如何显示信号高位的0 这个可能对一些有强迫症的有帮助吧 nand相关的操作,有一些特定的cmd,比如 r…...
czmq的4版本中CURVE怎么实现的两个程序之间使用的一个证书?
在CZMQ的4版本中,CURVE是一种加密机制,用于在两个程序之间建立安全的连接。要使用CURVE,你需要创建和分发公钥和私钥。以下是一个简单的步骤说明: 首先,你需要为每个程序生成一对公钥和私钥。你可以使用CZMQ的zcert类…...
Spring Boot整合Swagger
🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全栈,…...
SpringBoot-WebSocket浏览器-服务器双向通信
文章目录 WebSocket 介绍入门案例 WebSocket 介绍 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。 应用场景: 视…...
Docker网络模式_Docker常用命令_以及Docker如何给运行的镜像内容连接互联网_Docker网络模式原理---Docker工作笔记004
然后我们来看一下docker的网络模式: 这个docker我们先看一下电脑上的网络,有两个,1个是lo是测试用的一个是enp0s3这个是我们以太网地址,然后我们去: 安装docker 安装后我们再去ip address可以看到多出来一个网络是docker0 这里ip地址是172.17.0.1这个是私有地址外部无法访问 这…...
爬虫项目-爬取股吧(东方财富)评论
1.最近帮别人爬取了东方财富股吧的帖子和评论,网址如下:http://mguba.eastmoney.com/mguba/list/zssh000300 2.爬取字段如下所示: 3.爬虫的大致思路如下:客户要求爬取评论数大于5的帖子,首先获取帖子链接,…...
【Midjourney入门教程2】Midjourney的基础操作和设置
文章目录 Midjourney的常用命令和基础设置1、 /imagine2、 /blend3、 /info4、 /subscribe5、 /settings(Midjourney的基础设置)6、 /shorten 有部分同学说我不想要英文界面的,不要慌: 点击左下角个人信息的设置按钮,找…...
后端使用DES加密,前端解密方法
前言: 现在为了防止用户直接篡改数据会采用加密的方式进行传输,加密的方法有很多种,这篇文章主要讲解下后端使用DES加密的数据传输给前端,前端接收到之后如何去解密。 操作步骤如下: 1.安装crypto-js npm install c…...
chrome 扩展 popup 弹窗的使用
popup的基本使用方法 popup介绍 popup 是点击 browser_action 或者 page_action图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。 popup配置 V3版本中(V2版本是在 browser_action 中 )&#x…...
Spring Security入门教程,springboot整合Spring Security
Spring Security是Spring官方推荐的认证、授权框架,功能相比Apache Shiro功能更丰富也更强大,但是使用起来更麻烦。 如果使用过Apache Shiro,学习Spring Security会比较简单一点,两种框架有很多相似的地方。 目录 一、准备工作 …...
如何在 Unbuntu 下安装配置 Apache Zookeeper
简介 Zookeeper 是 apache 基金组织下的项目,项目用于简单的监控和管理一组服务,通过简单的接口就可以集中协调一组服务,如配置管理,信息同步,命名,分布式协调。 准备工作 Ubuntu 23.04 或者 20.04访问…...
AI视觉领域流媒体知识入门介绍(二):深入理解GOP
GOP(group of pictures) 在流行的视频编码算法中,都包含GOP这个概念,例如MPEG-2, H.264, and H.265。 背景 关于视频存储和传输的“size”: Resolution 分辨率 Uncompressed Bitrate 未压缩时的比特率 1280720 (720p…...
C++ 代码实例:并查集简单创建工具
文章目录 前言代码仓库代码说明main.cppMakefile 结果总结参考资料作者的话 前言 C 代码实例:并查集简单创建工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) 代码 说明 简单地创建并查集注…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...






