目录
[2.2 close](#2.2 close)
1.文件共识原理
- 文件 = 内容 + 属性
- 文件分为 打开的文件 和 未打开的文件
- 文件是由进程打开的,学习打开的文件,本质上是学习进程与文件之间的关系
- 没打开的文件存储在磁盘上,学习未打开的文件,主要是学习如何存储文件以让用户能够快速找到文件从而进行增删查改的操作
- 文件要被打开,那么文件一定要先加载到内存当中
- 进程 : 打开的文件 = 1 : n 也就是说,一个进程可以打开多个文件
- 操作系统通过先描述再组织的原理管理大量打开的文件:在内核中,一个被打开的文件都有自己的文件打开对象,包含着文件的许多属性。
2.文件系统调用接口
用户访问磁盘文件肯定需要访问磁盘,而用户只能通过操作系统访问磁盘,所以用户访问磁盘文件的函数或封装或直接使用了系统调用
2.1open

2参数的open函数显然是3参数open函数的子集,所以这里只介绍3参数的open函数
(1)pathname
pathname: 文件路径字符串
要么是绝对路径 (如 /home/user/file.txt),从根目录开始
要么只是相对路径 (./file.txt 或 ../file.log),相对于当前工作目录(CWD)。
(2)flags
flags: 打开标志,即用户以什么方式打开
- O_RDONLY:只读
- O_WRONLY:只写
- O_RDWR:读写
- O_CREAT:不存在则创建
- O_TRUNC:存在则清空
- O_APPEND:追加模式
- O_EXCL:与O_CREAT搭配,文件存在则失败
- O_NONBLOCK:非阻塞
打开方式是用宏定义的,这里通过宏定义的标志位以比特位方式组合传参的
一个int类型有32个比特位,每一位都可以充当一个标志位,从而进行传参

O_WRONLY | O_CREATE 从头开始覆盖写,不清空
常用组合:
O_RDONLY //只读
O_WRONLY | O_CREAT | O_TRUNC //不存在就创建,存在就清空从头开始写
O_WRONLY | O_CREAT | O_APPEND //不存在就创建,存在就从文件末尾开始写
(3)mode
mode:创建文件时的权限**(八进制)**,仅 O_CREAT 时有效
Linux下使用系统调用open创建不存在的文件时必须指定权限,否则权限就是乱码

成功创建合规的文件

可以是局部使用系统调用umask修改权限掩码,使得所创建的文件的权限为指定权限


(4)返回值
成功:返回文件描述符(fd) (非负整数) 失败:返回 -1,并设置 errno
(5)C语言fopen与open 的联系

2.2 close

参数fd指的是要关闭的文件描述符
close执行成功:返回 0
close执行失败:返回 -1,并设置
errno
3.访问文件的本质

Linux下:
- 进程拥有自己的描述对象 task_struct ,这其中包含一个 struct files_struct* 的指针,该指针用来指向 struct files_struct 结构体,该结构体中包含一个指针数组 struct file* fd_array[],该数组又叫做文件描述符表,每个进程有独立的 fd_array[]
- 操作系统为每一个打开的文件创建一个 struct file 结构体,用来描述打开的文件的信息,struct file 包含引用计数
- 进程与文件之间的联系是 task_struct 与 struct file 之间的联系,文件描述符存储着 struct file的指针,所以 task_struct 与 struct file 通过文件描述符进行联系
- task_struct → files_struct → fd_array[] → struct file
- 文件描述符唯一确定某个打开的文件,文件描述符的本质就是指针数组的下标
4.文件描述符
(1)概念
在进程中每打开一个文件,都会创建有相应的文件描述信息struct file,这个结构体指针被添加在pcb的struct files_struct中,以数组的形式进行管理,随即向用户返回数组的下标作为文件描述符,用于操作文件
(2)文件描述符的本质
文件描述符的本质就是指针数组的下标
(3)文件描述符的分配规则
最小未使用文件描述符策略:从下标0开始顺序查找没有被使用的数组位置,该下标就是新文件的文件描述符

进程运行起来后,自动打开标准输入文件(0:键盘文件)标准输出文件(1:显示器文件)标准错误文件(2:显示器文件),这是操作系统的特性,是程序员写代码的天然需要,是广大程序语言所必须遵守的规则
那么,在标准流没有被关闭或重定向的情况下,新打开的文件描述符通常从3开始
因为 Linux下访问文件只认文件描述符,所以C语言的FILE结构体一定封装了文件描述符

stdout(1)和stderr(2) 默认指向显示器文件,是两个独立的文件描述符,对应不同的struct file对象
printf 向标准输出文件(显示器文件)打印内容,文件指针是stdout,文件描述符是 1
C++中的文件流的本质与FILE结构体是类似的,直接或间接的包含了文件描述符