基础IO与文件系统

全文目录

  • C语言的文件操作函数
  • 系统调用接口
    • open
    • write
    • read
    • close
  • Linux中一切皆文件
  • 文件描述符
    • 重定向
  • 缓冲区
    • 为什么`fflush`能直接找到缓冲区进行刷新
  • 磁盘文件系统
    • 页表

C语言的文件操作函数

参考文章:

  1. C语言文件操作【基础知识 + 顺序读写 + 文件版通讯录】
  2. C语言文件操作收尾【随机读写 + 结束判定 + 文件缓冲区】

注意事项:

  1. 通过接口创建的文件是在当前路径下(进程的工作路径)
  2. C语言中的字符串结尾\0在文件中不起效,会出现乱码,所以向文件写入时不要将\0写入。

系统调用接口

open

基础IO与文件系统_第1张图片

mode:创建文件时文件的权限,同样受到umask掩码的限制。
	在进程中可以通过umask函数来设置该进程上下文的掩码

write

基础IO与文件系统_第2张图片

read

基础IO与文件系统_第3张图片

close

基础IO与文件系统_第4张图片

Linux中一切皆文件

OS中需要管理大量的硬件,不同硬件的读写方法都是不同的,意味着存在大量的读写函数。同时为了给用户提供良好的服务,要让用户看到所有的软硬件都是使用同样的接口 (write和read)。那么在创建文件描述符时的会根据不同的文件描述符和文件类型匹配不同的读写函数。

基础IO与文件系统_第5张图片

通过回调函数的方式调用具体的读写函数,在上层看来调用的都是文件的读写函数,所以一切皆文件。同样的,这也是多态的一种表现形式。

我们将存在于OS中的,文件属性数据结构的集合,称为虚拟文件系统(vfs)。通过对虚拟文件系统的管理,就可以摒弃掉底层硬件之间的差别,而统一使用文件接口的方式,来进行所有的文件(硬件)操作。

文件描述符

内核 ( k e r n e l ) (kernel) kernel利用文件描述符 ( f i l e d e s c r i p t o r ) (file descriptor) filedescriptor来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。 —— 百度百科

OS中的文件管理:

一个进程会打开大量的文件,被打开的文件需要管理,就会有文件相关的数据结构struct file来描述文件(内容 + 属性),不同的文件通过双链表链接起来。并通过指针数组file* fd_array[] 存放每个结构体的指针。 进程的PCB结构体中同样通过结构体struct files_struct来描述这个数组指针。文件描述符的本质就是存放struct file的指针数组的下标。

基础IO与文件系统_第6张图片

C语言的库函数原理:

在C语言程序中默认会打开三个标准输入输出流: s t d i n 、 s t d o u t 、 s t d e r r stdin、stdout、stderr stdinstdoutstderr,在OS中默认占用0、1、2三个文件描述符。C语言中的FILE结构体中包含系统的文件描述符,并在底层通过系统调用接口进行文件读写。

分配规则:

分配最小的、没有被占用的文件描述符

重定向

在Linux中一切皆文件,标准输入输出流也是文件。利用文件描述符的分配规则就能将标准输入输出流的文件描述符指向指定的文件,实现重定向。

本质:更改文件描述符的指向

系统调用接口

基础IO与文件系统_第7张图片

标准错误重定向:

./myfile > 1.txt 2>2.txt   
# 将1.txt的文件描述符指向的内容拷贝到1号文件描述符中
# 将2.txt的文件描述符指向的内容拷贝到2号文件描述符中


./myfile > 1.txt 2>&1  	
# 将1.txt的文件描述符指向的内容拷贝到1号文件描述符中
# 同时将1号文件描述符指向的内容拷贝到2号文件描述符中

缓冲区

为了提高整机效率,减少IO次数,C语言给每个文件提供了缓冲区,所有的硬件都是倾向于全缓冲的。但为了提高用户的体验,对于不同的设备,会采取不同的刷新策略。

刷新策略:

  • 显示器【行缓冲】
  • 磁盘【全缓冲】

缓冲区内的数据也是进程的数据,所以当fork创建子进程时也会发生写时拷贝。对于不同的设备,同样的代码可能发生不一样的结果。

为什么fflush能直接找到缓冲区进行刷新

在C语言层面,描述文件的是FILE类型的结构体,里面不仅仅封装了文件描述符,还包含了缓冲区信息。也就

syncfs(fd);  	# 将缓冲区的数据刷新到磁盘

磁盘文件系统

Linux管理磁盘上的文件时,是将内容和属性分开存储的,磁盘结构的参考文章:

文件系统结构

页表

磁盘以4kb大小为单位划分区域,这些区域被称为页帧,内存也以4kb为单位划分区域,这些区域被称为叶框。

程序加载到内存时,建立虚拟地址空间和页表,页表指向磁盘上的位置,当程序需要访问该数据时,需要先通过页表找到磁盘,然后将磁盘上的内容加载到内存,才能进行访问。临时将数据从磁盘加载到内存并进行访问的操作叫做缺页中断

页表也不是简单的映射关系,虚拟地址通过页表进行寻址的参考文章:

  1. 页表映射

  2. 操作系统概述 —— 一级页表与二级页表

总结:

  1. 其中的super block 和 GDT存放整个文件系统的对应信息。

  2. 目录也是文件,目录的datas block 中存放着文件名和inode编号的映射关系(目录权限对应目录的操作)

  3. 软链接就是创建快捷方式,有独立的inode编号

  4. 硬链接就是起别名,通过引用计数的方式共用同一数据

  5. 目录的起始链接数就是2, 当目录中多了一个目录计数++

你可能感兴趣的:(Linux,Linux)