Linux 0.11源码阅读笔记-文件管理

文件系统

生磁盘

未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件。

磁盘分区

生磁盘可以被分区,分区中可以安装文件系统,常见的文件系统有fat32、ext2、ext4等。分区后的磁盘结构布局如下图,其中主引导扇区记录了分区信息,并且包含引导代码可用于引导操作系统。

文件系统

分区内可以安装指定文件系统,同一磁盘多个分区文件系统不要求相同。MINIX文件系统布局如下:

  • 引导块:若作为引导分区,将存放操作系统的引导程序代码,否则空置。
  • 超级块:用于存放磁盘设备上文件系统结构的信息,说明各部分的大小。
  • i节点位图:标记i节点数据元素是否被使用
  • 逻辑块位图:标记磁盘数据块是否被使用
  • i节点区:用于存放inode节点数据,一个文件对应一个inode节点,inode节点存储文件属性数据。
  • 数据区:以固定大小盘块(1k)为单位进行动态分配和回收,用于存储数据,类似内存分页。

超级块

用于存放磁盘设备上文件系统结构的信息,说明各部分的大小。

图中列出的数据包含两部分:出现在盘上和内存中的字段和仅在内存中使用的字段,仅在内存中使用的字段是内核读取超级块后所附加的一些用于管理使用的字段信息。

inode节点

inode节点保存对应文件的属性信息,其中i_zone数组使用类似多级页表的方式维护文件数据块,即记录文件逻辑块到物理块之间的映射关系。

i_zone数组

i_zone数组包含直接盘块号、一次间接盘块号和二次间接盘块号。一次盘块号可视为单级页表,一次间接盘块号可视为二级页表、二次间接盘块号可视为三级页表。

这种处理方式的好处在于,对于小文件,通过直接块号可快速定位数据块;对于中等类型的文件,一次间接块可以维护较多数据块的同时,具有较快的访问速度;对于大型文件,二次间接盘块号可以维护大量磁盘块,但访问速度较慢。

内存多级页表与i_zone直接区别:不同进程具有固定大小的虚地址空间,并且对其整个虚地址空间的内存,都有可能访问到,因此使用多级页表。文件系统内存在很多大小不一的文件,综合考虑对不同大小文件的特点,使用1-3级磁盘块表可以分别处理小、中、大文件。

目录结构

  1. 树形目录结构

文件系统目录结构为树形,根节点为根目录,目录可以指向若干个子目录或子文件。

  1. 文件查找过程

通过文件inode节点,可以定位文件数据块,那如何通过文件路径定位到具体文件?

文件系统主要包含文件和目录两种文件,目录是一种特殊的文件,其文件内容存储其目录下文件名->inode节点号的映射信息。文件查找开始于根目录,根目录号固定为0,不需要查找即可直接打开。

举例说明文件查找过程,给定存在路径/name1/name2/name3查找具体文件过程:

1)通过根节点inode号,打开根目录,读取其文件内容,即目录下文件名->inode节点号映射表,找到name1目录inode节点号n1

2)通过name1的inode号n1,打开name1目录,读取其文件内容,即目录下文件名->inode节点号映射表,找到name1目录inode节点号n2

3)通过name2的inode号n2,打开name2目录,读取其文件内容,即目录下文件名->inode节点号映射表,找到name3目录inode节点号n3

4)通过name3的inode号n3,打开name3文件

  1. 文件数据块定位过程

1)打开文件:先通过文件查找找到文件inode节点号,然后打开文件,即读取inode至内存。

2)定位数据块:通过文件inode节点,访问其i_zone数组,进一步可以定位具体的数据所在磁盘块号。

文件链接

  • 硬链接

硬链接,在指定目录文件中,生成一个文件,即建立文件名->inode节点号的映射。不同之处在于,硬链接文件的inode号是其它文件的inode号,即多个文件共享一个inode。多个文件共享inode节点时,会引起inode节点引用计数增加。

硬链接示意图如下。

  • 软链接(符号链接)

软链接,在指定目录文件中,生成一个文件,建立文件名->文件路径的映射。软链接文件项不直接指向被指向文件的inode号,而是记录其文件路径。符号链接不直接共享inode,不会引起inode节点引用计数增加。

打开软链接文件时,先获取其指向的文件路径,再通过指向的文件路径打开文件。

软链接文件示意图如下,其中蓝色线表示软链接。

  • 删除被链接文件

硬链接:多个文件指向同一个inode节点,引用计数等于文件数量,删除其中一个文件,只会导致引用计数减小1,引用计数为零时,文件才会被删除。

软链接:删除软链接,不会对被指向文件产生任何影响;删除被指向文件,软链接可能会失效。

高速缓存

高速缓存是内核访问磁盘文件系统数据的必经之道,高速缓存用于解决CPU速度与磁盘IO速度不匹配的问题。因为CPU速度与磁盘IO速度差距较大,CPU同步读写磁盘数据,会导致CPU性能的浪费。

内核维护一个高速缓冲区池,按块使用和管理,可用于缓存磁盘数据,提高访问磁盘数据的性能。

buffer.c文件包含实现高速缓冲区的程序。内核代码通过指定设备号和逻辑块号来调用块读写函数。这些接口函数有,bread()、breada()、bread_page()。

  • bread:块读取函数
  • breada:块提前预读函数
  • bread_page:页块读取函数,一个内存页通常为4k大小、磁盘块通常为1k大小

文件系统相关函数

文件系统底层函数

该部分函数用于处理文件系统的元数据,包括超级块、位图、inode节点等。该部分函数被内核其它部分代码调用,不是提供给用户代码调用的系统调用接口。

文件系统底层处理函数包含在以下5个文件中:

  • bitmap.c:包含对i节点位图和逻辑块位图进行释放和占用处理函数,free_inode()、new_inode()、free_block()、new_block()

  • truncate.c:对数据文件长度截断为0的函数truncate(),可释放文件所有数据块。

  • inode.c:包含分配释放inode节点函数iget()和iput(),以及根据inode节点,获取文件逻辑块号函数bmap()。

  • namei.c:包含函数namei(),获取指定路径的inode节点

  • super.c:包的程序专门用于处理系统超级块,包括函数get_super()、free_super()等。还包括几个文件系统加载/卸载处理函数和系统调用,如sys_mount()等。

下图展示了文件系统不同部分对应的底层处理函数:

文件中数据的访问操作

该部分函数用于处理文件的读、写操作。

  1. 文件数据访问函数

用户程序调用read()、write()函数读写文件,read()、write()函数根据文件类型与其所在设备,进一步调用设备对应的读写函数如read_pipe()、write_pipe()等。

  1. 打开文件使用的内核数据结构

内核使用文件结构file、文件表file_table[]和内存中的i节点表inode_table[]来管理对文件的操作访问。

  • 文件指针数组。进程使用一个文件指针数组管理打开的文件,其中的文件指针(下标号)指向文件表中对应的文件结构file。每个进程有自己的文件指针数组。
  • 文件表:表项为file数据,用于在文件句柄于内存i节点项之间建立关系,其包含文件类型、访问属性、读写指针、文件句柄引用计数等信息。因为不同进程可能使用不同的访问模式打开同一文件,并且需要单独的读写指针等数据。所有进程共享文件表(file_table)。
  • 内存i节点表:表项存储i节点信息,存储所有进程打开文件的i节点信息。所有进程共享内存i节点表。

思考:文件描述符指向file结构、file结构指向内存inode节点,允许存在多对一的情况。什么场景会存在多个文件描述符指向同一个file结构;什么场景存在多个file结构指向同一个内存inode节点。

open同一个文件:多个file数据指向同一inode节点

dul同一文件描述符:多个文件描述符指向同一文件表项—file数据。

fork进程:仅复制文件描述符表

内核数据结构

file数据结构

文件和目录管理系统调用

  • open.c:实现文件管理相关的系统调用。主要包括创建、打开、关闭和属性修改。
  • exec.c:实现对二进制可执行文件和shell脚本文件的加载与执行,其中主要的函数为do_execve(),是exec()函数簇的主要实现函数。
  • fcntl.c:实现文件系统控制调用fcntl()和文件描述符的复制系统调用dup()、dup2()。dup主要用于多个文件描述符指向同一file结构的场景。
  • ioctl.c:实现输入/输出控制系统调用ioctl。主要调用tty_ioctl()函数,对终端io进行控制。
  • stat.c:实现取文件状态信息系统调用stat()和fstat。

总结

  1. MINIX文件系统空闲inode节点项和空闲磁盘块均通过位图管理,位图记录对应项是否空闲。
  2. 硬链接和软链接的区别在于,链接是直接指向inde节点,还是通过指向其他文件路径间接指向inode节点。
  3. linux内核具有io高速缓冲区,用于缓存磁盘数据,提高磁盘数据的访问效率。
  4. 打开文件内核数据结构具有三级映射关系:文件描述符->file数据->内存inode节点。open同一文件,多个file指向同一内存inode;dup文件描述符,多个文件描述符指向同一file。

Linux 0.11源码阅读笔记-文件管理的更多相关文章

  1. Linux 0.11源码阅读笔记-中断过程

    Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...

  2. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  3. Linux 0.11源码阅读笔记-总结

    总结 Linux 0.11主要包含文件管理和进程管理两个部分.进程管理包括内存管理.进程管理.进程间通信模块.文件管理包含磁盘文件系统,打开文件内存数据.磁盘文件系统包括空闲磁盘块管理,文件数据块的管 ...

  4. Linux 0.11源码阅读笔记-块设备驱动程序

    块设备驱动程序 块设备驱动程序负责实现对块设备数据的读写功能.内核代码统一使用缓冲块间接和块设备(如磁盘)交换数据,缓冲区数据通过块设备驱动程序和块设备交换数据. 块设备的管理 块设备表 内核通过一张 ...

  5. Linux 0.11源码阅读笔记-内存管理

    内存管理 Linux内核使用段页式内存管理方式. 内存池 物理页:物理空闲内存被划分为固定大小(4k)的页 内存池:所有空闲物理页组成内存池,以页为单位进行分配回收.并通过位图记录了每个物理页是否空闲 ...

  6. Linux 0.11源码阅读笔记-文件IO流程

    文件IO流程 用户进程read.write在高速缓冲块上读写数据,高速缓冲块和块设备交换数据. 什么时机将磁盘块数据读到缓冲块? 什么时机将缓冲块数据刷到磁盘块? 函数调用关系 read/write( ...

  7. Linux 0.11源码阅读笔记-高速缓冲

    高速缓冲 概念 高速缓冲区是内存中的一块内存,在块设备与内核其它程序之间起着一个桥梁作用.内核程序如果需要访问块设备中的数据,都需要经过高速缓冲区来间接的操作. 高速缓冲区结构 高速缓冲区被划分为1k ...

  8. 【从头到脚品读 Linux 0.11 源码】第一回 最开始的两行代码

    从这一篇开始,您就将跟着我一起进入这操作系统的梦幻之旅! 别担心,每一章的内容会非常的少,而且你也不要抱着很大的负担去学习,只需要像读小说一样,跟着我一章一章读下去就好. 话不多说,直奔主题.当你按下 ...

  9. linux 0.11 源码学习+ IO模型

    http://www.cnblogs.com/Fredric-2013/category/696688.html

随机推荐

  1. c/c++(c++和网络编程)日常积累(二)

    Linux下C编程通过宏定义打开和关闭调试信息 https://www.cnblogs.com/robinsons/p/3667032.html https://blog.csdn.net/u0134 ...

  2. python字符串格式化输出 %和format举例

    #!/usr/bin/env python # -*- coding: UTF-8 -*- #pyversion:python3.5 #owner:fuzj s1 = "i am %s, i ...

  3. 【Azure API 管理】使用APIM进行XML内容读取时遇见的诡异错误 Expression evaluation failed. Object reference not set to an instance of an object.

    问题描述 使用APIM,在 Inbound 中对请求的Body内容进行解析.客户端请求所传递的Request Body为XML格式,需要从Request Body中解析出多个(Element)节点值, ...

  4. JAVA——转义字符

    目录 1.Java转义字符 2.Java中的注释 2.1Java 中的注释类型 2.2文档注释 3.Java代码规范 4.Java开发注意事项和细节说明 1.Java转义字符 在控制台,输入 tab ...

  5. Flutter 设计模式|工厂模式家族

    文/ 杨加康,CFUG 社区成员,<Flutter 开发之旅从南到北>作者,小米工程师 在围绕设计模式的话题中,工厂这个词频繁出现,从 简单工厂 模式到 工厂方法 模式,再到 抽象工厂 模 ...

  6. 动手学TCP——CS144实验感想

    在Stanford CS144的课程实验Lab0~Lab4中,我们动手实现了一个自己的TCP协议,并且能够真的与互联网通信!此外,感谢Stanford开源本实验并提供了大量的优质测试用例,使得我们仅仅 ...

  7. 扩展我们的分析处理服务(Smartly.io):使用 Citus 对 PostgreSQL 数据库进行分片

    原文:Scaling Our Analytical Processing Service: Sharding a PostgreSQL Database with Citus 在线广告商正在根据绩效数 ...

  8. ASP.NET Core框架探索(一)

    今天我们来结合源码来探究一下ASP.NET CORE Web框架的运行原理. 可以先整体看一下下面这张基于源码分析过程的一个总结大纲,包含各环节完成的关键步骤: 下面我们将一起来结合源码探索启动一个A ...

  9. PHP pdf转png windows版本

    链接:https://pan.baidu.com/s/1Bli-2HkucRTYTeujkcsmjg&shfl=sharepset 提取码:2une 1.php_imagick扩展 (1)下载 ...

  10. laravel 根据字段不同值做不同查询

    在开发过程中我们经常遇到这种情况: 例如,一个信息表message,字段type 1.操作提醒 2.平台通知,表message_read记录当信息是平台通知时用户浏览状况 那么 当信息是平台通知时是针 ...