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++中面向对象的多态。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据库和表的管理】

数据库和表的管理 一、实验目的 了解MySQL数据库的逻辑结构和物理结构的特点。学会使用SQL语句创建、选择、删除数据库。学会使用SQL语句创建、修改、删除表。学会使用SQL语句对表进行插入、修改和删除数据操作。了解MySQL的常用数据类型。 二、实验内容SQL语句创建、选择、删…

玩转硬件之MP3的破解

MP3播放器是一种能播放音乐文件的播放器,主要由存储器(存储卡)、显示器(LCD显示屏)、中央处理器MCU(微控制器)或解码DSP(数字信号处理器) 等组成。 其中微控制器是播放器…

k8s存储卷之动态

动态pv需要两个组件 1、卷插件,k8s本身支持的动态pv创建不包含NFS,需要声明和安装一个外部插件 Provisioner 存储分配器,动态创建pv,然后根据pvc的请求自动绑定和使用 2、StorageClass,用来定义pv的属性&#xff0c…

金蝶云星空单据转换插件-选单

文章目录 金蝶云星空单据转换插件-选单 金蝶云星空单据转换插件-选单 选单使用标识报错 应该使用实体属性

LeetCode 每日一题 Day 44 || 哑节点去重

82. 删除排序链表中的重复元素 II 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 示例 1: 输入:head [1,2,3,3,4,4,5] 输出:[1,2,5] 示例 2&#x…

内存泄漏问题

内存泄漏是一种常见的问题,它可能导致系统内存不断增加,最终耗尽可用内存。解决内存泄漏问题通常需要进行调试和分析。下面是一些可能有助于解决内存泄漏问题的步骤: 1. 监控内存使用情况: a. 使用 malloc 记录日志:…

MyBatisPlus学习笔记二

接上:MyBatisPlus学习笔记一: MyBatisPlus学习笔记一-CSDN博客 1、条件构造器 MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。 1.1、集成体系 1.2、实例 查询 lambda查询 更新 1.3、总结 2、自定义sql 我们可以利用MyB…

Rust-NLL(Non-Lexical-Lifetime)

Rust防范“内存不安全”代码的原则极其清晰明了。 如果你对同一块内存存在多个引用,就不要试图对这块内存做修改;如果你需要对一块内存做修改,就不要同时保留多个引用。 只要保证了这个原则,我们就可以保证内存安全。 它在实践…

入门Docker1: 容器技术的基础

目录 服务器选型 虚拟机 基于主机(物理机或虚机)的多服务实例 基于容器的服务实例 Docker Docker三要素 Docker安装 Docker基本使用 基本操作 仓库镜像 容器 服务器选型 在选择服务器操作系统时, Windows 附带了许多您需要付费的功能。 Linux 是开放源代…

光K8S的目录结构就够你学一天!

Kubernetes Project Layout设计 Kubernetes项目由Go语言编写。Go语言官方对项目的结构设计没有强制要求,早期的Go语言开发者都喜欢将包文件代码放置在项目的src/目录下,如nsqio开源项目,开发者喜欢将入口文件放入apps/目录。不同开发者的喜好…

使用WAF防御网络上的隐蔽威胁之CSRF攻击

在网络安全领域,除了常见的XSS(跨站脚本)攻击外,CSRF(跨站请求伪造)攻击也是一种常见且危险的威胁。这种攻击利用用户已经验证的身份在没有用户知情的情况下,执行非授权的操作。了解CSRF攻击的机…

运筹说 第45期丨多目标规划发展及其提出者—— Abraham Charnes和William W. Cooper

经过前面的学习,相信大家已经对运筹学的运输问题有了更加全面的了解,接下来小编将带你学习新一章的内容, 先来看看多目标规划的发展简史,然后再带你领略该理论两位提出者的传奇一生! 01目标规划发展简史 Vilfredo Pa…

Vue2.组件通信

样式冲突 写在组件中的样式默认会全局生效。容易造成多个组件之间的样式冲突问题。 可以给组件加上scoped属性,让样式只作用于当前组件。 原理: 给当前组件模板的所有元素,加上一个自定义属性data-v-hash值,用以区分不同的组件。…

【Axure高保真原型】移入放大对应区域的饼图

今天和大家分享移入放大对应扇形区域的饼图的原型模板,鼠标移入时,对应扇形区域的会放大,并且的项目和数据弹窗,弹窗可以跟随鼠标移动。这个原型是用Axure原生元件制作的,所以不需要联网或者调用外部图表……具体效果可…

一篇教你生成密钥给自己打的exe添加密钥

一篇教你生成密钥给自己打的exe添加密钥 我这里是自己写了一个python 打包exe,说总是给我报毒什么的 文章目录 一篇教你生成密钥给自己打的exe添加密钥前言一、使用java jdk 自带的keytool?二、进行转换2.把证书密钥写入到你的exe 总结 前言 生成密钥并为自定义 .…

上海市税务局:买卖虚拟货币需缴税!中国仍未有放松加密政策的迹象?

自2021年央行等十部委下发禁止虚拟货币交易的通知以来,国内虚拟货币交易平台几乎销声匿迹。然而,最近一则关于个人所得税的释义再次引起了人们的关注。 1月5日,国家税务总局上海市税务局在官方公众号发布《个人所得税经营所得和分类所得常见误…

Win10专业版系统搭建DNS解析服务

Win10专业版 纯新手,也没弄过Linux的。不喜勿喷,有问题请指出 第一天一头雾水整了几个小时没结果,第二天豁然开朗,10分钟明白了第一天的问题所在。 Win10 安卓: iOS: 搭建DNS服务器的意义: 屏蔽…

关于Python —— Python教程

开始 Python 是一个易于学习、使用和高效阅读的编程语言。它具有简洁的英文语法,编写更少的代码,让程序员专注于业务逻辑而不是语言本身。 本教程将从深度、专注细节上去理解 Python 这门语言。初学者可以参考此教程理解相应的内容,本教程将…

高精度磁导航传感器MGS系列RS232|RS485|CANBUS通讯连线方法

高精度磁导航传感器MGS系列,包含:CNS-MGS-080N、CNS-MGS-160N等,具有1mm的检测精度,特别适应于⾼精度磁条导航。利⽤检测磁场相对位置来进⾏AGV的辅助定位对接,获得更⾼的导航、定位、驻⻋精度。 MGS系列磁导航传感器⽀…