Linux文件系统数据在内存和磁盘之间的传输
【Linux文件系统】数据在内存和磁盘之间的传输
———————————————————————————————————————————
每日鸡汤:一万个美丽的未来,抵不上一个温暖的现在;每一个真实的现在,都是我们曾经幻想的未来,愿你爱上现在,梦见未来。
———————————————————————————————————————————
一:磁盘与物理内存的数据交互
物理内存与磁盘之间的数据交换一般是以 4KB 为单位来交互的。 页框 是物理内存的划分单位,用于实际存储数据。 页帧 是虚拟内存的划分单位,通过页表映射到页框。那么为什么要使用 4 KB 的大小来交互呢?
- 硬件层面上,减少 IO 的次数,即减少访问外设的次数来提高效率。 例如,一次访问 4KB 数据和 4 次访问 1KB 数据相比,明显的前者效率更加高效。因为磁盘是一个机械设备,访问周期很长。一次访问4KB的 CPU 只与磁盘交互一次,磁头和盘面只需进行一次定位就可读取 4KB 的内容,后者4次读取 1KB 的内容,且这四次可能不连续,意味着磁头和盘面要定位4次,大量的机械运动就导致了效率的下降。
- 软件层面上,基于局部性原理的预加载机制。 尽管当前 CPU 和磁盘只需要访问50字节数据,但是 OS 和磁盘之间还是以 4KB 为单位来数据交互将数据加载到内存。
二:操作系统对物理内存的管理
操作系统是一定能看到物理内存的,即能看到物理内存的物理地址的。而对物理内存的管理,既然要管理,还是要 “先描述,再组织” ,在OS内核中有一个结构体 struct page 用来描述物理内存的。
一个 struct page 对象就对应一个 4KB 的内存空间,对象内部页记录了一些 4KB 的相关属性信息【当前页框状态,引用计数等等】。所以操作系统就可以将物理内存划分为一个个的 struct page 对象,用数组的形式组织起来,数组的下标为对应的页号。假设共有 4GB 的内存,那么 【41024102410244 / (4*1024) 】,大约等于100w左右,即在 4GB 的物理内存中大约含有100w左右个 struct page 对象。
随便给一个地址【一个地址一个字节】,求它所对应的页号。 物理地址 / (4KB = 4*1024字节) ,即使用该地址按位与上 0xFFFFF000 ,将低12为清零就是该地址所对应的页号。找到对应的页号了,就能在系统中找到对应的物理页框。所有申请内存的动作,都是在访问 page 数据,对这个数组进行增删查改。
struct page 对象内部有一个 flags 属性,通过 flags 属性来判断当前页是否被使用,即获取当前页框的状态。若没有被使用,申请内存时,flags置为1,那么就表示当前页框已经被申请成功了。
三:再次理解文件的打开
3.1:文件页缓冲区的引入
因为 struct file 是内核中的一个数据结构,用来描述一个被打开的文件。 inode 是磁盘那里引入的。磁盘上一个文件只对应一个 inode ,内部包含文件的属性。那么它们两者之间有什么关系呢?
struct file 只记录了文件的少量属性,所以在内核中还有一个 struct inode 结构体专门描述一个文件的所有属性。即在 struct file 中有一个指针字段来指向该文件的 struct inode 对象。
文件都是内容+属性的。在磁盘上文件属性使用 inode 来存储,内容使用 DataBlock 来存储,所以在内核中,使用 struct inode 来存储文件属性,使用 struct address_space 来存储文件的内容。【采用页缓冲区的方式来存储文件的内容, struct file 结构体中有一个 struct address_space 字段的指针】, struct address_space 内部有一个 struct radix_tree_root 的结构体对象,本质上就是一个字典树状结构。树内的每一个结点都是 struct radix_tree_node 类型。类型中有个 void* slots 属性。内部存的是 struct page 对象的地址。故此,在 struct file 结构体中的有物理内存的指针。就将这些物理内存称作是 文件页缓冲区。
3.2:向文件中写入数据
在向文件中写入的时候,首先将内容写入到用户缓冲区。然后再在合适的是时候将内容刷新到页缓冲区中。之后再在合适的时候刷新到外设。这些操作全部都是由 IO 子系统来执行的,进程不会关心。所以在 OS 上肯定会存在着非常多的 IO 操作,因为可能会有很多进程都要将数据写入磁盘中,所以操作系统会将所有的 IO 操作管理起来(“先描述,再组织”)。内核中有 struct request 结构专门来管理 IO 操作的,有时为了提高效率,OS 还会将 IO排序和 IO 合并,以减少磁盘和盘面的定位次数。
在 Linux 中,我们的每一个进程,打开的每一个文件都要有自己的 inode 属性和自己的文件页缓冲区。
四:结语
今天的分享到这里就结束了,今日给大家分享了关于进程的终止情况。如果各位看官觉得还不错的话,可以三连支持一下欧。各位的支持就是捣蛋鬼前进的最大动力!