Linux Kernel - mount系统调用

本文介绍了Linux Kernel中的mount系统调用,详细讲解了如何挂载Minix文件系统,包括Boot block、Super block等组成部分。通过mount调用流程,分析了get_fs_type、minix_mount等关键步骤,揭示了文件系统与设备驱动的交互过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列目录传送门

Linux Kernel - 文件系统系列


mount系统调用简介

玩过linux的同学对mount系统调用都不会陌生, shell命令mount正是调用内核中的sys_mount函数完成文件系统的挂载. 比如下面的命令:

lqp@lqp-ThinkPad-T540p:~/mnt$ sudo mkfs.minix /dev/ram0
21856 inodes
65535 blocks
Firstdatazone=696 (696)
Zonesize=1024
Maxsize=268966912

lqp@lqp-ThinkPad-T540p:~/mnt$ sudo mount -t minix /dev/ram0 ramdisk

在/dev/ram0中的Ram disk中创建minix文件系统, 并挂载到ramdisk目录下. 这样, 访问ramdisk目录时实际上访问的就是/dev/ram0设备中的minix文件系统, 该文件系统将数据存储在Ram Disk中. 用户通过文件系统的接口与物理磁盘设备交互.

接下来的内容中, 让我们来看一看mount系统调用是如何将文件系统和具体的设备关联起来的.


Minix文件系统示意图

图片取自网络
这里写图片描述
查看原图

从上可以看到, 磁盘块按功能分5部分:
1. Boot block - 用来存放boot loader, 方便操作系统加载的
2. Super block - 用来描述整个文件系统的属性的, 比如inode个数, 设备数据块总数量等
3. I-nodes bitmap和Zone bitmap - 用来管理分配inode和数据页的bitmap, 每一bit代表一个对应的inode或者zone(即数据块)对象
4. inode block - 用来存放inode数据, inode数据中存放了文件的属性, 如文件大小, 创建时间, 文件的数据块对应的块号等
5. 文件的数据块

每一个block对应1024字节, 对应2个扇区(sector, 512字节), 除此之外还有一个重要的概念, page, 对应虚拟内存的内存页面大小, 一般是4096个字节. 这几个概念会不断穿插在文件系统中. 这里简单归纳一下:

  • page - 内存管理相关, 是MMU管理的对象, 可以直接映射到地址空间
  • 文件系统block - 也叫逻辑块, 不同的文件系统可以定义不同的block size
  • sector - 磁盘设备的读取单位, 传统设备的是512字节, 像ssd这种可以配置成一次读取4k. 不过在block io层, 面向设备接口sector对应的是512字节, 设备可以根据自身特性做适配. 在Ram Disk驱动的内部, 就是按4K的page来组织数据的.

约束关系: sector size <= 文件系统block size <= page size, 且成2的指数倍关系.


mount调用流程


如下图所示:
sys_mount
查看原图

其中关键调用点有:

  • step 4: get_fs_type()
  • step 8 : minix_mount()
  • step 11: minix_fill_super()

接下来我们挨个来看一下.


1. get_fs_type()

struct file_system_type *get_fs_type(const char *name)
{
    struct file_system_type *fs;
    const char *dot = strchr(name, '.');
    int len = dot ? dot - name : strlen(name);

    fs = __get_fs_type(name, len);
    if (!fs && (request_module("fs-%.*s", len, name) == 0))
        fs = __get_fs_type(name, len);

    if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
        put_filesystem(fs);
        fs = NULL;
    }
    return fs;
}

可以看到, 该函数接受的是字符串参数, 对minix而言, 则是字符串 “minix”, 然后调用内部函数__get_fs_type来查找内部注册的文件系统链表. 如果链表中没有找到, 那么还会主动加载对应文件系统的驱动来注册所需要的文件系统类型, 然后再查找一次.查找过程中调用了find_filesystem函数, 如下所示:

//lqp comment: 文件系统的查找是简单的根据名字查找文件系统链表

static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
    struct file_system_type **p;
    for (p = &file_systems; *p; p = &(*p)->next)
        if (strncmp(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值