Linux文件系统和个人理解

Linux文件系统和个人理解

记录Linux文件系统基础和个人理解


关键概念

1.inode 和 block

文件是存储在硬盘上的,硬盘的最小存储单位叫做扇区sector,每个扇区存储512字节。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个块block。这种由多个扇区组成的块,是文件存取的最小单位。块的大小,最常见的是4KB,即连续八个sector组成一个block。

文件数据存储在块中,那么还必须找到一个地方存储文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种存储文件元信息的区域就叫做inode,中文译名为索引节点,也叫i节点。因此,一个文件必须占用一个inode,但至少占用一个block。

  • 元信息 → inode
  • 数据 → block

2.页缓存

linux中页缓存的本质就是对于磁盘中的部分数据在内存中保留一定的副本,使得应用程序能够快速的读取到磁盘中相应的数据,并实现不同进程之间的数据共享。

3.页表

进程访问虚拟内存,CPU执行时通过分页机制转换成物理内存访问,虚拟地址到物理内存的转换表称为页表,这个转换是个查表的过程。

同一程序运行起来的两个进程,虚拟地址空间相同,但对应的物理空间是不一定相同的。OS需要给每个进程设置一份页表,在进程调度过程中,上下文切换阶段会做页表的切换。

4.file结构体

struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。
它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。

File

5.mmap

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。


文件读写过程

1.进程调用库函数read()向内核发起读文件的请求;
2.内核通过检查进程的文件描述符定位到虚拟文件系统已经打开的文件列表项,调用该文件系统对VFS的read()调用提供的接口;
3.通过文件表项链接到目录项模块,根据传入的文件路径在目录项中检索,找到该文件的inode;
4.inode中,通过文件内容偏移量计算出要读取的页;
5.通过该inode的i_mapping指针找到对应的address_space页缓存树—基数树,查找对应的页缓存节点;
(1)如果页缓存节点命中,那么直接返回文件内容;
(2)如果页缓存缺失,那么产生一个缺页异常,首先创建一个新的空的物理页框,通过该inode找到文件中该页的磁盘地址,读取相应的页填充该页缓存(DMA的方式将数据读取到页缓存),更新页表项;重新进行第5步的查找页缓存的过程;

File System


个人理解

1.mmap和普通io的速度对比

mmap相比,read和write执行了更多的系统调用,并做了更多的复制。read和write将数据从内核缓冲区中复制到应用缓冲区,然后再把数据从应用缓冲区复制到内核缓冲区。而mmap则直接把数据从映射到地址空间的一个内核缓冲区复制到另一个内核缓冲区。当引用尚不存在的内存页时,这样的复制过程就会作为处理页错误的结果而出现(每次错页读发生一次错误,每次错页写发生一次错误)。

所以他们两者的效率的比较就是系统调用和额外的复制操作的开销和页错误的开销之间的比较,哪一个开销少就是哪一个表现更好。

2.突然断电的情况怎么保证写入成功

普通io的写入不一定会成功,要看脏数据有没有回写后备存储。系统只有适当时机(内存低于一定阈值或者超过一定时长)才会把页缓存的写到后备存储。显式的调用fsync、fdatasync或者sync的时候,内核按照要求执行回写操作。

3.fd文件描述符怎么跨进程传递

由于每个进程的文件描述符列表都不一样,对应的是已打开文件列表的序号,A进程的fd传到B进程是没法使用的,一种办法是,通过内核调用,通过A进程的fd找到对应的inode,然后为B进程试生成一个新的fd,可以参考binder的实现,因为binder持有所有调用进程的task_struct,binder就为fd传递实现了这些操作。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×