Linux操作系统——文件详解

1.文件理解预备知识

首先,当我们在磁盘创建一个空文件时,这个文件会不会占据磁盘空间呢?

答案是当然会占据磁盘空间了,因为文件是空的,仅仅指的是它的内容是空的,但是该文件要有对应的文件名,文件的大小,文件的创建时间,文件的权限等等,这些叫做文件的属性,是一个往往被人们所忽略的非常关键的一个点,所以我们都说文件=内容+属性。

1.所有对文件的操作,无非就两种操作:a.对内容做操作   b.对属性做操作

2.文件内容是数据,文件属性也是数据 ---- 所以说存储文件既是存储内容数据,也是存储属性数据 ----- 默认就是在磁盘上的文件。

3.我们要访问一个文件的时候,都是要先把这个文件先打开。

这里所说的我们指的是谁呢?是指我们用户吗?

我们平常在写我们的c语言代码来对文件进行操作的时候并不是写好了这个文件就会通过fopen函数直接打开了,而是要通过将代码运行起来编译形成可执行程序将其加载到内存中,然后变成进程进而来打开文件并对文件进行操作的,所以说这里的我们指的是进程,而并不是指的我们用户。 

我们下面再来谈谈文件打开前与文件打开后的状态。

文件打开前:普通的磁盘文件   文件打开后:将文件加载到内存。我们上面说文件是存储在磁盘上的,既然要将文件加载到内存,根据冯诺依曼体系结构,那么就必然要涉及到访问磁盘设备,而访问磁盘设备只有操作系统有资格来访问,所以这一步必定是操作系统来做。

4.一个进程可以打开多个文件吗?多个进程可以打开多个文件吗?

加载到内存中被打开的文件可能会存在多个。进程:打开的文件 = 1:n

所以根据2、3、4这几点我们可以知道操作系统在运行中,可能会打开很多个文件,那么操作系统就需要对这些文件进行管理。那么如何管理呢?先描述,在组织。

一个文件要被打开,一定要先在内核中形成被打开的文件对象,说白了就是在c语言上我们需要用struct结构体来对文件进行描述,然后用链表链接起来,所以对文件的管理就转化成了对链表的增删查改。

其实说的更准确一点就是一个进程是通过操作系统来打开文件的,而操作系统不相信任何人,所以操作系统一定要给我们提供系统调用接口。

5.文件按照是否被打开分为  被打开的文件和没有被打开的文件

其中被打开的文件是存在于内存中的,而没有被打开的文件存在于磁盘中。

6.研究本次文件操作的本质:进程与被打开文件的关系

2.复习常见C语言的文件接口

我们先来看看c语言对文件操作的一些接口

打开文件接口:

写入文件接口:

关闭文件接口:

利用这些接口我们用以下代码进行测试:

运行结果:

然后我们把代码修改成如下方式来进行测试:

运行结果:

发现我们之前写入到log.txt的内容不见了,只剩下了刚刚新写入的内容。

而我们打开文件有以下几种方式来进行打开:

我们刚刚是以w的方式打开文件的,也就是写的方式:这种方式打开文件,如果文件不存在就会创建一个新的文件,如果需要打开的文件存在就会先清空文件中的内容,然后再打开文件进行写入。

用重定向的方式来写就是:

下面我们以a方式进行打开文件测试:

运行结果:

发现追加在了后面,这种a方式打开文件也是写入,只不过不会清空文件,而是在文件结尾处进行写入,也就是追加,不会清空文件内容。

同时也可以用重定向的方式对文件内容进行追加:

还有一种方式是以读的方式打开文件,也就是r方式。

3.认识系统调用接口,操作文件

我们学习的c语言打开文件的接口,底层一定封装了系统调用接口!!!

下面我们看一下打开文件的系统调用接口的手册:

这里的open接口有两个参数的接口,也有三个接口的参数,我们下面会来进行介绍,而这个open还有一个int类型的返回值,这个返回值叫做文件描述符fd.

我们先来对open接口的第二个参数来进行理解:

这里的flags我们称之为标志位,是一个int类型的整数,它里面有32个bit位,所以理论上我们可以用这32个bit位为0为1进行分别传参,如果要传一个标志位,那我们就可以用第一个比特位来表示,如果要传两个标志位,那么我们就可以用第一第二个比特位来表示,三个标志位就用三个,十个就用是个bit位来传。所以这个参数可以同时传递多个标志位的,而我们的标志位有O_RDONLY(只读标志位),O_WRONLY(只写标志位),O_RDWR(读写标志位)等等。这些大写的标志位都是用宏来定义的。

下面我们写一段测试代码来进行理解:

然后运行:

所以我们可以通过宏的方式为接口传递多个标志位。

下面我们再对open接口进行测试:

我们先把之前创建的文件都删除了,然后重新执行这段代码:

我们发现确实形成了一个log.txt的文件,可是为什么是红色的呢?同时它的权限也很奇怪,当我们创建文件的时候,必定是要经过linux权限创建的,但是我们刚刚创建该文件的时候并没有指明该文件的权限,所以log.txt这个临时文件的权限是一个乱码式的权限。

如果我们用open接口来打开文件,如果文件不存在,那就需要在使用open接口的时候给文件传递一个权限参数:

也就是调用这个接口:

我们先把之前的log.txt这个临时文件删除了然后重新执行上述代码:

我们发现权限跟我们传进去的并不一致,我们设置的是0666,应该是显示-rw-rw-rw-的,可是发现最后一个权限w不见了。原因就在于我们创建一个文件时在我们系统中有一个默认的权限掩码umask:

默认是0002,但是如果我们就是想要设置为0666呢?

那么我们就可以通过修改umask权限掩码为0即可

然后运行之后:

发现权限变回了0666.但是一般我们都不会去修改系统的umask.

下面我们对文件进行操作:

先看一个写文件的系统调用接口:write

使用该write接口,其中fd是文件描述符,buf是字符串首地址,count是需要写入的大小。

运行之后:

下面我们再修改代码:

把写入的内容修改一次

发现在open接口中以只写的方式打开文件如果文件不存在会创建文件,如果文件存在不会清空文件,而是从文件的开始对文件内容进行覆盖式的写入,如果我们想像c语言那个接口那样先清空文件内容再写入该怎么写呢?其实很简单,只需要在标志位上再加上一个O_TRUNC这个宏即可,下面把代码进行修改:

运行结果:

c语言中还有一种追加的方式打开文件,在系统调用接口open需要传参O_APPEND标志位即可,即把代码改成:

运行结果:

我们发现文件内容是追加上去的。

4.尝试着理解文件,打通语言与系统关于文件部分的理解

所以我们通过上述的说明可以知道如下结论:

除了了解了这些open系统调用参数,想必大家也一定对我们的open的返回值fd比较好奇是什么吧,下面我们就对这个fd进行测试:

一个进程可以打开多个文件

运行之后:

文件描述符分别是3,4,5,6,同时四个文件也创建出来了。

我们发现这是一个连续的小整数逐渐递增的,我们平时遇到这种都是以数组下标最为常见,而且我们也发现怎么没有0,1,2呢?

理解文件在操作系统中的表现:

那么0,1,2去哪了呢?

我们看一下linux内核中源代码进程结构体中的files_struct* 

以上都是内核源代码中跟文件有关的结构体。

进程在运行的时候默认打开标准输入流,标准输出流,标准错误流三个文件,他们对应的文件描述符分别是0,1,2 。

通过上述的说明,我们知道,操作系统访问文件,只认文件描述符!!!

那么我们前面谈到的c语言库函数中的FILE是什么东西呢?是一个C语言提供的结构体类型,既然是结构体,那么这个结构体里面必定封装了文件描述符!!!如何证明呢?

运行结果:

所以我们初步得出了一个结论,不仅仅是fopen底层封装了open系统调用接口,文件的结构体类型也进行了封装。所以操作系统只认fd.

1.操作系统为什么要把0,1,2 ,stdin,stdout,stderr打开呢?

就是为了让程序员默认进行输入输出代码编写!

2.stderr是什么呢?

3.如何理解一切皆文件?

我们的设备像显示器,键盘,网卡,声卡,扬声器等等这些都是可以输入输出的,我们用另一种说法就是读和写,如果没有读,那么读就为空,如果没有写,那么写就为空,所以我们都可以把这些设备都看成有一个共同点,那就是都有读写方法。

这种方式的实现其实就是我们c++中面向对象的多态。

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

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

相关文章

Redis图形界面闪退/错误2系统找不到指定文件/windows无法启动Redis/不是内部或外部命令,也不是可运行的程序

Redis图形界面闪退/错误2系统找不到指定文件/windows无法启动Redis/不是内部或外部命令,也不是可运行的程序 我遇到了以上的问题。 其实,最重要的原因是我打开不了another redis desktop mannager,就是我安装了之后,无法打开它…

【嵌入式学习笔记-02】什么是库文件,静态库的制作和使用,动态库的制作和使用,动态库的动态加载

【嵌入式学习笔记-02】什么是库文件,静态库的制作和使用,动态库的制作和使用,动态库的动态加载 文章目录 什么是库文件?编程模型的发展什么是库文件? 静态库的制作和使用动态库的制作和使用动态库的动态加载 什么是库文…

Docker-01-安装基础命令

Docker-01-安装&基础命令 文章目录 Docker-01-安装&基础命令一、Docker是什么?二、安装Docker①:卸载旧版②:配置Docker的yum库③:安装Docker④:启动和校验⑤:配置镜像加速01:注册阿里云…

SpringBoot知识02

1、快速生成mapper和service (1)(自动生成简单的单表sql) (2)快速生成多表(自动生成常量) 2、springboot配置swagger(路径不用加/api) (1&#…

Mindspore 公开课 - GPT

GPT Task 在模型 finetune 中,需要根据不同的下游任务来处理输入,主要的下游任务可分为以下四类: 分类(Classification):给定一个输入文本,将其分为若干类别中的一类,如情感分类、…

报名活动怎么做_小程序创建线上报名活动最详细攻略

报名活动怎么做:一篇让你掌握活动策划与营销的秘籍 在当今社会,无论是线上还是线下,活动已经成为企业营销和品牌推广的重要手段。但是,如何策划一场成功的活动呢?这篇文章将为你揭示活动策划与营销的秘籍,…

政采网调试要求及常见问题解决方法

登录平台软件环境要求: 操作系统:建议Win10及以上(Win10-64位专业版 版本号17134纯净安装版本) 浏 览 器:IE11浏览器、谷歌120.0.6099.217(64位正式版)浏览器 必要软件:CA互联互通…

Mindspore 公开课 - BERT

BERT BERT模型本质上是结合了 ELMo 模型与 GPT 模型的优势。 相比于ELMo,BERT仅需改动最后的输出层,而非模型架构,便可以在下游任务中达到很好的效果;相比于GPT,BERT在处理词元表示时考虑到了双向上下文的信息&#…

微服务架构设计核心理论:掌握微服务设计精髓

文章目录 一、微服务与服务治理1、概述2、Two Pizza原则和微服务团队3、主链路规划4、服务治理和微服务生命周期5、微服务架构的网络层搭建6、微服务架构的部署结构7、面试题 二、配置中心1、为什么要配置中心2、配置中心高可用思考 三、服务监控1、业务埋点的技术选型2、用户行…

2023年总结:雄关漫道真如铁,而今迈步从头越,今朝得失

2023年悄然离去,感谢大家的帮助、鼓励和陪伴,感谢家人的理解和支持,祝大家新年快乐,阖家幸福,身体健康。像往常一样,今年也会写一篇年终总结,也是自己的第11篇年终总结,题目就叫《雄…

32 二叉树的定义

之前的通用树结构 采用双亲孩子表示法模型 孩子兄弟表示法模型 引出二叉树 二叉树的定义: 满二叉树和完全二叉树 对此图要有印象 满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树 小结

Javaweb之SpringBootWeb案例员工管理分页查询的详细解析

3. 员工管理 完成了部门管理的功能开发之后,我们进入到下一环节员工管理功能的开发。 基于以上原型,我们可以把员工管理功能分为: 分页查询(今天完成) 带条件的分页查询(今天完成) 删除员工&…

HNU-算法设计与分析-实验4

算法设计与分析实验4 计科210X 甘晴void 202108010XXX 目录 文章目录 算法设计与分析<br>实验41 回溯算法求解0-1背包问题问题重述想法代码验证算法分析 2 回溯算法实现题5-4运动员最佳配对问题问题重述想法代码验证算法分析 3 分支限界法求解0-1背包问题问题重述想法…

gogs git创建仓库步骤

目录 引言创建仓库clone 仓库推送代码 引言 Gogs 是一款类似GitHub的开源文件/代码管理系统&#xff08;基于Git&#xff09;&#xff0c;Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。 创建仓库 git中的组织可以把它看成是相关仓库的集合&#xff0c…

DNS主从服务器配置

主从服务器配置&#xff1a; &#xff08;1&#xff09;完全区域传送&#xff1a;复制整个区域文件 #主DNS服务器的配置【主dns服务器的ip地址为192.168.168.129】 #编辑DNS系统配置信息&#xff08;我这里写的增加的信息&#xff0c;源文件里面有很多内容&#xff09; [root…

python中小数据池和编码

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 ⼀. 小数据池 在说小数据池之前. 我们先看⼀个概念. 什么是代码块: 根据提示我们从官⽅⽂档找到了这样的说法&#xff1a; A Python program is constructed from code blocks. A block is a piece of Python program text…

大电流直流恒温控制电路

一个电子制冷器控制芯片 实物照片 驱动芯片 使用环境12V直流&#xff0c;电流10A 特此记录 anlog 2024年1月15日

2.1.2 一个关于y=ax+b的故事

跳转到根目录&#xff1a;知行合一&#xff1a;投资篇 已完成&#xff1a; 1、投资&技术   1.1.1 投资-编程基础-numpy   1.1.2 投资-编程基础-pandas   1.2 金融数据处理   1.3 金融数据可视化 2、投资方法论   2.1.1 预期年化收益率   2.1.2 一个关于yaxb的…

【C初阶——内存函数】鹏哥C语言系列文章,基本语法知识全面讲解

本文由睡觉待开机原创&#xff0c;转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言&#xff0c;共同进步&#xff01; 这里写目录标题 1.memcpy使用和模拟实现2.memmove的使用和模拟实现3.memset函数的使用4.memcpy函数的使用 1.m…

linux安装MySQL5.7(安装、开机自启、定时备份)

一、安装步骤 我喜欢安装在/usr/local/mysql目录下 #切换目录 cd /usr/local/ #下载文件 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz #解压文件 tar -zxvf mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz -C /usr/local …