【进程IO】详细讲解文件描述符fd

文章目录

  • 前言
  • 什么叫文件描述符
    • FILE与fd的关系
  • 再次理解文件
    • 为什么要有文件的方法列表呢?
  • 进程和struct file的关系
  • 再次理解open操作

前言

C语言的关于文件操作的各种函数实际上是对系统调用的封装。那么从进程的角度看,一个文件到底是如何被描述的呢?又是如何被组织并管理的呢?
在此之前,如果对C语言以及系统调用关于文件相关内容的知识还不太了解或许需要复习的同学,可以去看我之前的博客:
C语言关于文件概述以及文件操作
关于文件的系统调用

什么叫文件描述符

所有的I/O设备都被模型化为文件,而所有的输入输出都被当成对文件的读写操作。这种将设备优雅地映射为文件的方式,允许Linux内核引出一个简单的,低级的应用接口,成为Unix I/O,着使得所有的输入输出都能以一种统一切一致的方式来执行,这也是为什么说linux下一切皆文件。

当程序通过要求内核打开相应的文件。内核会返回一个小的非负整数。这个非负整数就叫做描述符,也叫文件描述符。文件描述符是用于唯一标识文件的号码。下面我用fd表示文件标识符。

也就意味着,我们的进程实际上并不记录文件本身,而只需要记录一个为一个文件ID。所有被打开的文件的信息都被集中在一起被内核管理,内核向进程提供文件的接口。

在这里插入图片描述
尝试打开多个文件并观察其文件描述符:
在这里插入图片描述

在这里插入图片描述
我们发现打开的文件其ID是从3开始的,这是属于巧合吗?
其实并不是
Linux shell 创建的每一个进程开始的时候都有三个打开的文件:标准输入流(fd=0),标准输出流(fd=1),标准错误流(fd=2)。这三个文件分别对应的硬件设备是键盘、显示器、显示器。

在c语言中也会默认给我们打开三个文件
在这里插入图片描述
如何证明这三个文件会默认打开呢?
在这里插入图片描述

在这里插入图片描述

对于以上结果,我们可以直接在stdout文件里写入数据,说明了stdout文件确实是被默认打开了!

再证明stdout文件的描述符是1,看代码:
在这里插入图片描述
在这里插入图片描述
这里使用系统调用的write函数直接向文件描述符为1的文件写入数据。我们发现文件标识符1指的就是stdout文件。由此,证明了进程会默认打开stdout文件,并且该文件的fd=1.其余两个文件也是同样的道理。

FILE与fd的关系

FILE是C语言用来描述文件的一个结构体,在了解了文件描述符之后,我们其实也能明白FILE的底层实现了对fd的封装

再次理解文件

以用户的视角来看,文件=属性+内容。以操作系统的视角来看,文件其实就是一个名为filestruct

每当我们打开一个文件,操作系统就会生成一个struct file记录该文件的所有信息,包括以何种方式打开,文件的标记位等。并将这个file以双链表的形式加入到所有打开文件的集合中,这个集合统一由操作系统管理

其中值得我们关注的是,struct file内部会包含一个指针,指向该文件的内核级缓存区。进程就是在这个区域里面进行读写数据。该区域的存在避免了进程直接向磁盘读写数据,提高了效率(缓冲区存在的意义)。
在这里插入图片描述
除此之外,struct file里还含有文件的类型以及该文件的方法列表。方法列表包括了open方法,write方法等。

为什么要有文件的方法列表呢?

首先所有的硬件都有一定的存储能力。这也就意味着我们能以看待磁盘的视角来看待其他硬件。比如显示器,键盘等。我们所说的什么键盘文件其实就是用来跟键盘的存储空间打交道的不同硬件读写数据的操作方法可能不一样。比如键盘文件就没有向其写数据的方法,我们只能从键盘读取而不能写入
所以方法列表中的元素其实就是一个函数指针,指向对应硬件的读写方法。
虽然各个硬件中的读写方法存在差异,但是相同功能的函数名字可以一致。
这样操作系统就能以统一的视角来看待各个硬件的读写方法。

进程和struct file的关系

一个进程可以打开多个文件,对于进程来说,被打开的文件同样也算是一种资源。
为了区分一个进程拥有的“打开文件”集合。操作系统为每个进程建立了一张
struct files_struct表,表中有一个struct file*数组fd_array,这个数组就指向该进程所有的打开的文件。task_struct中的 struct files_struct* files指针就指向这张表。
在这里插入图片描述

fd_array是文件映射关系数组。fd_array数组中的每个元素都是对应操作系统管理文件集合中的某个文件。于是我们就能通过下标访问该数组,从而在操作系统管理文件集合中找到目标文件

非常合理的,文件描述符就是fd_array数组的下标!!!
这样我们也就明白了,文件操作的系统调用为什么是用fd来做参数的。因为我们能通过fd准确地找到目标文件。

再次理解open操作

在明白文件是如何被描述以及如何被管理之后,我们也就能更加深刻的理解系统调用open打开文件的过程:

1.创建struct file(包括fd)
2.开辟文件缓存区,加载文件中的数据(延后)
3.查进程的文件描述符表(fd_array数组)
4.将file的内存地址填入到fd_array[fd]中
5.返回fd.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/292189.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java数据结构】关于栈的操作出栈,压栈,中缀表达式,后缀表达式,逆波兰表达式详解

🔥个人主页:努力学编程’ 🔥内容管理:java数据结构 上一篇文章我们讲过了java数据结构的链表,对于链表我们使用了它的一些基本操作,完成了扑克牌小游戏的操作,如果你感兴趣的话,点…

了解 LoadRunner 性能测试软件及其基础使用

目录 一、了解LoadRunner 1、什么是Loadrunner? 2、Loadrunner包括什么组件? (1)前台组件 (2)后台组件 二、LoadRunner三大组件 1、VuGen(虚拟用户脚本生成器) (…

Vue + .NetCore前后端分离,不一样的快速发开框架

摘要: 随着前端技术的快速发展,Vue.NetCore框架已成为前后端分离开发中的热门选择。本文将深入探讨Vue.NetCore前后端分离的快速开发框架,以及它如何助力开发人员提高效率、降低开发复杂度。文章将从基础功能、核心优势、适用范围、依赖环境等…

linux基础命令篇:Linux基础命令讲解——文件浏览(cat、less、head、tail和grep)

Linux基础命令讲解——文件浏览(cat、less、head、tail和grep) 本文详细介绍Linux中的cat、less、head、tail和grep命令,这些命令在日常工作中非常实用,以下是关于这些命令的详细介绍: 1. cat命令:用于查看…

JDK8的下载安装与环境变量配置教程

前言 官网下载:Java Archive Downloads - Java SE 8u211 and later 现在应该没人用32位的系统了吧,直接下载Windows x64 Installer jdk-8u391-windows-x64.exe 一、安装JDK 1. 打开jdk-8u391-windows-x64.exe 2. 直接下一步 3. 这个地方不要动他&…

鸿蒙OS开发实例:【瀑布流式图片浏览】

介绍 瀑布流式展示图片文字,在当前产品设计中已非常常见,本篇将介绍关于WaterFlow的图片浏览场景,顺便集成Video控件,以提高实践的趣味性 准备 请参照[官方指导],创建一个Demo工程,选择Stage模型熟读Har…

构建操作可靠的数据流系统

文章目录 前言数据流动遇到的困难先从简单开始可靠性延迟丢失 性能性能损失性能——分层重试 可扩展性总结 前言 在流式架构中,任何对非功能性需求的漏洞都可能导致严重后果。如果数据工程师没有将可伸缩性、可靠性和可操作性等非功能性需求作为首要考虑因素来构建…

单例设计模式(3)

单例模式(3) 实现集群环境下的分布式单例类 如何理解单例模式中的唯一性? 单例模式创建的对象是进程唯一的。以springboot应用程序为例,他是一个进程,可能包含多个线程,单例代表在这个进程的某个类是唯一…

mybatis标签解析教程

mybatis标签解析 标签结构 我们在mapper的xml文件中&#xff0c;使用动态SQL&#xff0c;那么这些标签<where>、<if>、<set>、<ForEach>、<Choose>、<Trim> 等是怎么解析的呢&#xff1f;我们先看包的结构 包结构中&#xff0c;script…

【Qt】:多种方式编辑hello world

多种方式编辑hello world 一.QLabel二.对象树三.使用单行编辑框四.使用按钮 (小技巧&#xff1a;1.可以使用F4来进行头文件和对应cpp文件的切换&#xff1b;2.写完一个函数的声名之后,按下altenter,就可以自动的在对应的cpp 文件中添加函数的定义了.) 一.QLabel 注意这里是QSt…

第九届蓝桥杯大赛个人赛省赛(软件类)真题C 语言 A 组-分数

solution1 直观上的分数处理 #include <iostream> using namespace std; int main() {printf("1048575/524288");return 0; }#include<stdio.h> #include<math.h> typedef long long ll; struct fraction{ll up, down; }; ll gcd(ll a, ll b){if…

相册清理大师-手机重复照片整理、垃圾清理软件

相册清理大师是一款超级简单实用的照片视频整理工具。通过便捷的操作手势&#xff0c;帮助你极速整理相册中的照片和视频、释放手机存储空间。 【功能简介】 向上滑动&#xff1a;删除不要的照片 向左滑动&#xff1a;切换下一张照片 向右滑动&#xff1a;返回上一张照片 整理分…

【2023】kafka在linux和docker安装(kafka-1)

目录&#x1f4bb; 一、linux安装kafka1. 安装jdk2. 上传解压到/usr/local目录下3、使用kafka 二、docker安装kafka1. 下载2. 安装zookeeper3. 安装kafka 一、linux安装kafka 环境主机 mac m2、虚拟机Ubuntu22.04.4 1. 安装jdk yum install -y java-1.8.0-openjdk.x86_64下载k…

电商系统秒杀三 秒杀兜底方案之熔断降级

一 秒杀场景介绍 1.1 秒杀场景的特点 1、秒杀具有瞬时高并发的特点&#xff0c;秒杀请求在时间上高度集中于某一特定的时间点&#xff08;秒杀开始那一秒&#xff09;&#xff0c;这样一来&#xff0c;就会导致一个特别高的流量峰值&#xff0c;它对资源的消耗是瞬时的。 2、…

LATTICE进阶篇DDR2--(1)获取官网DDR2例程并仿真

前言 本章主要讲述如何从官网下载DDR2的DEMO例程&#xff0c;并将例程的仿真运行起来。 官网的DEMO在Diamond工程里是没有调用任何任何IP核的&#xff0c;只是在仿真的时候调用了CORE文件夹下的IP核源文件进行仿真&#xff0c;该DEMO工程主要是拿来产生仿真波形&#xff0c;对…

算法学习——LeetCode力扣图论篇2

算法学习——LeetCode力扣图论篇2 1020. 飞地的数量 1020. 飞地的数量 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相…

这回轮到鸿蒙禁用安卓了!!!

1月18日&#xff0c;鸿蒙生态千帆仪式上&#xff0c;华为正式宣布了HarmonyOS NEXT&#xff08;下简称鸿蒙星河版或纯血鸿蒙&#xff09;开发者预览已向开发者开放申请&#xff0c;纯血鸿蒙开始走向普及阶段。伴随着不再兼容安卓的纯血鸿蒙铺开&#xff0c;鸿蒙走进了运营属于自…

本地虚拟机服务器修改站点根目录并使用域名访问的简单示例

说明&#xff1a;本文提及效果是使用vmware虚拟机&#xff0c;镜像文件是Rocky8.6 一、配置文件路径 1. /etc/httpd/conf/httpd.conf #主配置文件 2. /etc/httpd/conf.d/*.conf #调用配置文件 调用配置文件的使用&#xff1a; vim /etc/httpd/conf.d/webpage.conf 因为在主配…

python opencv之提取轮廓并拟合圆

图片存储地址为&#xff1a;C:\Users\Pictures\test.png&#xff0c;该图像图片背景是黑色的&#xff0c;目标区域是亮的&#xff0c;目标区域是两段圆弧和两段曲线构成的封闭区域&#xff0c;其中两段圆弧属于同一个圆&#xff0c;但在目标区域的相对位置&#xff0c;也就是不…

CrossOver软件2024免费 最新版本详细介绍 CrossOver软件好用吗 Mac电脑玩Windows游戏

CrossOver是一款由CodeWeavers公司开发的软件&#xff0c;它可以在Mac和Linux等操作系统上运行Windows软件&#xff0c;而无需在计算机上安装Windows操作系统。这款软件的核心技术是Wine&#xff0c;它是一种在Linux和macOS等操作系统上运行Windows应用程序的开源软件。 Cross…