预备
- 1 ···> 对文件操作,本质是IO
- 2 ···> 文件的组成
- 3 ···> 打开文件
- 3.1、“打开”的本质
- 3.2、为什么要打开文件
- 3.3、“谁”来打开文件
- 4 ···> 文件与系统调用
- 总结
现在我们进入了Linux中的“文件”部分。
我们先从“基础IO”说起。要学习“基础IO”,我们就要先学习一些预备知识(也许是知识回顾),以做好准备。
1 ···> 对文件操作,本质是IO
当前我们认为,文件保存在磁盘当中。
磁盘可以对文件进行永久存储。磁盘属于冯诺依曼体系中的外部设备,即外设。
所以,我们对文件进行的一系列操作,本质上都是对外设(磁盘)的输入、输出——这就是IO(input和output)。
小贴士1
对文件的一系列操作就是IO,我们要站在内存的角度去理解:
文件未来是要被加载到内存当中的。对于内存中的文件,
- 向文件写入内容的时候,键盘等输入设备就需要输入内容到内存中(因为文件此时也在内存中),这就是 Input ;
- 读取文件的内容,比如输出到显示屏上的时候,内存就需要输出文件内容到输出设备上,这就是 Output 。
2 ···> 文件的组成
我们知道,文件由两部分组成:
3 ···> 打开文件
对文件的操作,可以分为:
- 对内容做操作
- 对属性做操作
操作文件之前,我们首先需要打开文件。对于“打开文件”,我们有三个问题:
- 打开文件的“打开”,本质是什么?
- 为什么要打开文件?
- 谁来打开文件?
3.1、“打开”的本质
“打开”的本质,是把文件从磁盘加载(拷贝)到内存当中。
小贴士2
加载文件,也分为:
- 加载文件的属性
- 加载文件的内容
但是操作系统,并不一定会将文件的内容,全部加载到内存中。(等真正要用的时候再全部加载进来)
3.2、为什么要打开文件
这是由计算机体系结构规定的,即冯诺依曼体系结构。
因为用户只能通过CPU,访问加载到内存中的文件,
- 用户没办法自己直接访问磁盘上的文件(如果有办法,那还要计算机干嘛😅)
- CPU也不能直接在磁盘上访问文件,CPU只能与内存进行交互
3.3、“谁”来打开文件
是用户吗?好像不是。
用户写好代码并保存,代码中包含fopen函数,那么此时文件就被打开了吗?并没有。用户写好了代码,而文件依旧“躺在”磁盘中没被动用。
只有代码被编译、链接成可执行文件,CPU执行可执行文件里的代码,fopen函数才能被执行,文件才能被打开。
而CPU要想执行可执行文件,必须对进程进行调度。所以,文件的打开,由进程来完成。
比如,我们在shell命令行上执行cat main.c,
- 父进程bash就会创建一个子进程;
- 子进程通过程序替换的方式,将
cat的代码加载到内存中,并与子进程建立联系; - 运行
cat命令读取main.c内容并写入到屏幕上,那么进程就必须能够打开文件。
所以,学习对文件的操作,本质上是学习进程和文件之间的关系。
小贴士3
磁盘文件分为两类:
- 被进程打开的文件
- 未被进程打开的文件
被进程打开的文件,就是加载到内存中被打开的文件。对于这一类文件的操作,侧重于进程与文件的关系。
未被进程打开的文件,就是磁盘中保存的文件。对于这一类文件的操作,侧重于文件系统的管理。目前我们讨论的“基础IO”,就是在讨论:如何操作被进程打开的文件。
4 ···> 文件与系统调用
磁盘是硬件,访问文件需要访问磁盘。
用户想访问文件,必须通过操作系统完成。用户无法直接使用操作系统,必须借助系统调用:
所以,操作系统必须提供系统调用,以使得用户能够访问文件。
总结
学习基础IO的准备知识,总结为:
- 对文件进行的一系列操作,本质上都是对外设(磁盘)的输入、输出——IO
- 文件 = 属性(元数据) + 内容
- 学习对文件的操作,本质上是学习进程和文件之间的关系
- 操作系统必须提供系统调用,以使得用户能够访问文件