文件基础和文件fd

news/2024/5/25 3:57:08

文章目录

  • 预备知识
  • C语言的文件接口
  • 系统调用
  • 文件fd

正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通俗易懂,风趣幽默,忍不住分享一下给大家。 点击跳转到网站。

预备知识

我们平时说文件就是说文件里面有什么,那么空文件有大小吗?答案肯定是有的,我们平时所说的文件除了文件的内容以外还存在文件的创建时间,大小等等,这是文件的属性,所以文件 = 内容 + 属性的。所以我们对文件的操作无非就是对文件内容或者对文件属性的操作。不管是内容还是属性,它们本质都是数据,所以他们被存储在磁盘中,就是磁盘文件。所以我们要访问一个文件的时候都是要把这个文件打开的,该文件被打开前就是磁盘文件,被打开后,因为CPU只和内存打交道,所以被打开的文件一定会被加载到内存。所以加载磁盘文件,一定会访问外设,这部分工作是由OS来做的。
一个进程是可以打开很多文件的,所以进程和文件的比例关系一定是 1 :n 。而在我们的系统中是有很多进程的,所以被打开的文件也可能会非常的多,所以OS要对这些文件进行管理,管理的本质就是先描述在组织,因此在OS中存在struct file结构体来描述文件,所以以后打开一个文件就创建一个file结构体,把他们用链表链起来,对文件的管理就成了对该链表的增删查改。

C语言的文件接口

C语言打开文件的是fopen
在这里插入图片描述
第一个参数就是打开文件的名称,可以使用绝对路径也可以使用相对路径,第二个参数是打开的模式,经常用的就是w以写的方式打开,但是每次打开都会清空文件,不存在就创建,还有一种常用的是a以追加的方式打开,每次打开不会清空文件,直接在文件结尾进行写入,依然是不存在就创建。还有r方式,是以只读的方式打开。经常用的就是这三种模式。
我们会发现w模式和我们指令所讲的输出重定向非常像。
在这里插入图片描述
a模式和追加重定向非常相似。
在这里插入图片描述

系统调用

我们再来认识一个系统调用open。
在这里插入图片描述
open函数是一个系统用调用,它的第一个参数就是文件名,和fopen一样,但是第二个参数是标志位。标志位有很多但是这里我们只介绍常用的几种。第三个参数是文件的权限,一般来说只有创建文件的时候需要设置。

关于函数传入标志为的技巧是Linux中常用的传参方式,接下来给兄弟们演示一下什么叫做标志位传参。

#include <stdio.h>#define Print1 1
#define Print2 (1 << 1)
#define Print3 (1 << 2)
#define Print4 (1 << 3)void printflag (int flag)
{if(flag & Print1) printf("i am Print1\n");if(flag & Print2) printf("i am Print2\n");if(flag & Print3) printf("i am Print3\n");if(flag & Print4) printf("i am Print4\n");
}
int main()
{printflag(Print1);printf("============================\n");printflag(Print1 | Print2);printf("============================\n");printflag(Print1 | Print2 | Print3);printf("============================\n");printflag(Print1 | Print2 | Print3 | Print4);printf("============================\n");return 0;
}

在这里插入图片描述
所以open的第二个参数第原理和这个基本上是差不多的,它的选项常用的O_WRONLY(只写)、O_RDONLY(只读)、O_CREAT(不存在就创建)、O_TRUNC(每次打开时清空文件)、O_APPEND(追加写,不清空文件)。open的返回值是一个fd(文件描述符),它是用来表示一个文件的。所以C语言中的FILE也一定封装了这个数字。有了这些选项的基础,我们可以来模仿实现一下fopen的各个选项的实现。

FILE _fopen(const char * str, char c)
{int flag = 0;int is_read;if(c == 'a'){flag = O_WRONLY | O_APPEND | O_CREAT;}else{if(c == 'w'){flag = O_WRONLY | O_TRUNC | O_CREAT;}else{if(c == 'r'){flag = O_RDONLY;is_read = 1;}else{//TODO}}}int fd = 0;if(is_read){fd = open(str, flag, 0x666);if(fd < 0){perror("open");exit(-1);} }else{fd = open(str, flag);if(fd < 0){perror("open");exit(-1);} }FILE file;// _fileno就是文件描述符file._fileno = fd;return file;
}

所以C语言的所有库函数的本质都是封装了系统调用。

文件fd

到这里我们可以来尝试理解一下文件了。如何在系统层面上理解一下文件呢?
我们知道每个进程在被创建是都是会有自己的PCB的,在Linux中也就是task_struct,所以每个进程的PCB中都有一个struct files_struct* files 的指针,这个指针指向的结构体中有一个非常重要的一张表,struct file* fd_array[],这是一个指针数组,我们打开的每一个文件都会被在这个指针数组中被指向,一般来说是从小到大来排列的,而数组的下标就是我们上面系统调用返回的文件描述符。所以文件描述符的本质就是数组的下标。操作系统访问文件只认识文件描述符。
在这里插入图片描述
我们进程在运行的时候,是会默认打开三个流,标准输入流、标准输出流、标准错误流。这三个流对应的硬件分别是键盘、显示器、显示器。因为Linux下一切皆文件,所以这三个流在进程被打开时会一次把文件描述符表的0、1、2位置给占了,所以我们自己打开的文件的fd一般是从3开始从小到大排的。
在这里插入图片描述
OS默认打开三个流,就是为了我们程序员默认进行输入输出的代码的编写。

我们如何理解一切接文件?
在file文件中是有函数指针的,所以对于不同的文件我们让它的文件指针指向对应的方法,如果没有改方法的话我们让这个指针指向空就行了,所以在上层看来,文件就是这个方法,但是它是可能对于不同的文件指向的方法也是不同的。
在这里插入图片描述


http://www.mrgr.cn/p/47212868

相关文章

cyi青少年CTF擂台挑战赛 2024 #Round 1 wp

cyi青少年CTF擂台挑战赛 2024 #Round 1 wpWEB EasyMD5 靶机真不敢恭维 一个文件上传界面,得上传pdf传两个pdfhttps://www.cnblogs.com/wysngblogs/p/15905398.html 这篇文章看到md5碰撞,找到个工具fastcoll_v1.0.0.5 https://www.win.tue.nl/hashclash/后续写的wp,flag可能…

Gitlab Runner自动推送Docker映像

接上文,增加两个stage 最简单的推送,其实是在docker build后边带上--push的开关即可。 但是不经过测试就上传,Docker仓库里很快会堆满垃圾。 所以我们设计新增两个场景,经过测试之后才push映像去仓库。 stages:- build-docker-image- test- push-image variables:PAY_IMAGE…

黑马JavaWeb课程中安装vue脚手架出现的问题

1 安装node.js 要想前端工程化&#xff0c;必须安装node.js&#xff0c;前端工程化的环境。 在成功安装node.js后&#xff0c; 修改全局包安装路径为Node.js安装目录&#xff0c; 修改npm镜像源为淘宝镜像源&#xff0c;这里出现第一个问题&#xff0c;视频中给的淘宝镜像为&…

python实现常见一元随机变量的概率分布

一. 随机变量 随机变量是一个从样本空间 Ω \Omega Ω到实数空间 R R R的函数&#xff0c;比如随机变量 X X X可以表示投骰子的点数。随机变量一般可以分为两类&#xff1a; 离散型随机变量&#xff1a;随机变量的取值为有限个。连续型随机变量&#xff1a;随机变量的取值是连…

关于Windows 10的兼容模式,看这篇文章就够了

这篇文章解释了如何使用Windows兼容模式在Windows 10上完美地运行旧版本的Windows程序。 如何更改Windows 10兼容模式设置 如果疑难解答没有完成任务&#xff0c;并且你知道该程序以前使用过哪个版本的Windows&#xff0c;则可以手动更改Windows 10兼容模式的设置&#xff1a…

Spring-自动配置

自动配置流程细节梳理: 1、导入starter-web:导入了web开发场景1、场景启动器导入了相关场景的所有依赖:starter-json、starter-tomcat、springmvc 2、每个场景启动器都引入了一个spring-boot-starter,核心场景启动器。(上面三个也有) 3、核心场景启动器引入了spring-boot-a…

[回归指标]R2、PCC(Pearson’s r )

R2相关系数 R2相关系数很熟悉了&#xff0c;就不具体解释了。 皮尔逊相关系数&#xff08;PCC&#xff09; 皮尔逊相关系数是研究变量之间线性相关程度的量&#xff0c;R方和PCC是不同的指标。R方衡量x和y的接近程度&#xff0c;PCC衡量的是x和y的变化趋势是否相同。R方是不…

《TCP/IP详解 卷一》第9章 广播和组播

目录 9.1 引言 9.2 广播 9.2.1 使用广播地址 9.2.2 发送广播数据报 9.3 组播 9.3.1 将组播IP地址转换为组播MAC地址 9.3.2 例子 9.3.3 发送组播数据报 9.3.4 接收组播数据报 9.3.5 主机地址过滤 9.4 IGMP协议和MLD协议 9.4.1 组成员的IGMP和MLD处理 9.4.2 组播路由…

Gitlab Runner自动制作C#网站项目的Docker映像

概述 代码签入Gitlab后,Gitlab Runner自动执行docker build,构建网站应用的Docker映像。 在Visual Studio 2022中创建解决方案在Gitlab中创建项目 这一步省略。 签入源代码到Gitlab为项目添加Dockerfile在解决方案根目录下创建“.gitlab-ci.yml” stages:- build-docker-imag…

Docker容器(3)单容器管理

一、单容器 1.1概念简介 Docker三个重要概念: 仓库(Repository); 镜像(Image); 容器(Container). *Docker的三个重要概念是仓库(Repository)、镜像(Image)和容器(Container)**。具体如下&#xff1a; **镜像(Image)**&#xff1a;Docker镜像是创建容器的基础&#xff0c;它类似…

LabVIEW非接触式电阻抗层析成像系统

LabVIEW非接触式电阻抗层析成像系统 非接触式电阻抗层析成像&#xff08;NEIT&#xff09;技术以其无辐射、非接触、响应速度快的特点&#xff0c;为实时监测提供了新的解决方案。基于LabVIEW的电阻抗层析成像系统&#xff0c;实现了数据的在线采集及实时成像&#xff0c;提高…

工作感受月记(2024年03月)

2024年03月01日 周五下午班,自己手中事情多了起来了。 今日工作事项: 1/ 一个aks 中应用连接redis案例,为什么会出现间歇性的连接到redis的public ip地址呢? 2/ key vault案例,客户从aws上连接azure服务。应该是她们内网环境没有打通引起的。 3/ 自己另外做了什么事情呢? …

FRM模型十二:极值理论

目录 极值理论介绍GEVPOT 代码实现 极值理论介绍 在风险管理中&#xff0c;将事件分为高频高损、高频低损、低频高损、低频低损。其中低频高损是一种非常棘手的损失事件&#xff0c;常出现在市场大跌、金融体系崩溃、金融危机以及自然灾害等事件中。 由于很难给极端事件一个准…

《哈利波特》1-7册全集高清PDF

《哈利波特》简介 《哈利波特》这个系列的图书自1997年在英国问世以来,迄今在全世界已发行超过四亿多册,创造了出版史上的奇迹,全套共7册,分别是:《Harry Potter and the Philosopher’s Stone 哈利波特与魔法石》、《Harry Potter and the Chamber of Secrets 哈利波特与…

【Vue3】自定义 Vue3 插件(全局实现页面加载动画)

// main.ts import { createApp } from vue import App from ./App.vue import Loading from "./components/Loading/index.ts";const app createApp(App) type Lod {show: () > void,hide: () > void } //编写ts loading 声明文件放置报错 和 智能提示 decl…

十八:Java8新特性

文章目录 01、Java8概述02、Java8新特性的好处03、并行流与串行流04、Lambda表达式4.1、Lambda表达式使用举例4.2、Lambda表达式语法的使用14.3、Lambda表达式语法的使用2 05、函数式(Functional)接口5.1、函数式接口的介绍5.2、Java内置的函数式接口介绍及使用举例 06、方法引…

C++类开发的第六篇(虚拟继承实现原理和cl命令的使用的bug修复)

Class_memory 接上一篇末尾虚拟继承的简单介绍之后,这篇来详细讲一下这个内存大小是怎么分配的。 使用cl cl 是 Microsoft Visual Studio 中的 C/C++ 编译器命令。通过在命令行中键入 cl 命令,可以调用 Visual Studio 的编译器进行编译操作。cl 命令提供了各种选项和参数,用…

Unity—MVC分层开发思想

每日一句&#xff1a;当你不努力的时候&#xff0c;天赋就会一点一点被收回 目录 MVC分层开发思想 MVC是什么 MVC的开发步骤 案例&#xff1a;点击按钮实现金币进行添加&#xff0c;并且把金币记录到JSON里 MVC模式实现 背包系统基础代码 背包项目实现步骤 MVC分层开发思…

web自动化——Selenium 之下拉

一、select下拉列表Select类处理select-option1)导入Select类 from selenium.webdriver.support.select import Select2)确保你要操作的元素是select。实例化Select类 Select()3)找到select元素对象 select_ele=driver.find_element(By.NAME,cars)4)将select对象作为参数 s…

Servlet快速入门

注:出自黑马程序员