操作系统内核 实验四

实验目的

  1. 掌握文件系统的工作机理
  2. 理解文件系统的主要数据结构
  3. 学习较为复杂的Linux下的编程
  4. 了解EXT2文件系统的结构

准备知识

外存管理

文件系统层次结构如下

目录管理

文件系统接口

命令接口

程序接口

Linux的EXT2文件系统

  • EXT2文件系统结构

  • 数据地址安排

实验步骤

  1. 输入命令make编译该文件系统:成功build modules(该实验是在root用户下实现的,不需要输入sudo)

  2. 输入命令insmod aufs.ko安装模块

  3. 使用dmesg命令查看模块是否安装成功

    在使用dmesg命令后,输出了相当多的模块信息

    在输出信息的最后,可以发现语句如下,表示模块已经安装成功.

    1
    2
    3
    [ 1861.402049] create inode cache success
    [ 1861.402056] register filesystem success
    [ 1861.402059] aufs module loaded
  4. 输入命令mount -o loop -t aufs ./image ./dir挂载设备

  5. 使用命令dmesg再次打印模块输出,可以查看挂载是否成功.

    获得了super block的相关信息super block结构是指文件系统在磁盘分区的特殊位置中存储的文件系统参数集,包括:

    1. magic
    2. 索引节点块——inode blocks
    3. 块大小——block size
    4. 根节点——root inode
    5. 块中的索引节点数——inodes in block
  6. 卸载模块前必须先卸载已挂载的文件系统,否则会出现以下错误 :
    image-20191111022536623

  7. 输入mount指令查看已挂载的设备,找到挂载的文件系统及其挂载点为/root/桌面/filesystem/image/root/桌面/filesystem/dir
    image-20191111022608021

  8. 卸载系统后,卸载模块。在卸载已挂载的设备时,该设备不能有进程在运行。
    image-20191111022828188

  9. 再输入dmesg命令显示已卸载。
    image-20191111022905569

核心代码分析

本次实验代码的核心在inode分配函数

aufs_fill_sb函数

在为根目录创建dentry(目录项)之前,应创建根目录的索引节点(索引节点)。索引节点结构可能是文件系统中最重要的一种。每个文件系统对象(文件,文件夹,特殊文件,杂志等)都用inode标识。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static int aufs_fill_sb(struct super_block *sb, void *data, int silent)
{
struct inode *root = NULL;

sb->s_magic = AUFS_MAGIC_NUMBER;
sb->s_op = &aufs_super_ops;

root = new_inode(sb);
if (!root)
{
pr_err("inode allocation failed\n");
return -ENOMEM;
}

root->i_ino = 0;
root->i_sb = sb;
root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
inode_init_owner(root, NULL, S_IFDIR);

sb->s_root = d_make_root(root);
if (!sb->s_root)
{
pr_err("root creation failed\n");
return -ENOMEM;
}

return 0;
}

aufs_inode_fill函数

负责填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static void aufs_inode_fill(struct aufs_inode *ai,
struct aufs_disk_inode const *di)
{
ai->ai_block = be32_to_cpu(di->di_first);
ai->ai_inode.i_mode = be32_to_cpu(di->di_mode);
ai->ai_inode.i_size = be32_to_cpu(di->di_size);
ai->ai_inode.i_blocks = be32_to_cpu(di->di_blocks);
ai->ai_inode.i_ctime.tv_sec = be64_to_cpu(di->di_ctime);
ai->ai_inode.i_mtime.tv_sec = ai->ai_inode.i_atime.tv_sec =
ai->ai_inode.i_ctime.tv_sec;
ai->ai_inode.i_mtime.tv_nsec = ai->ai_inode.i_atime.tv_nsec =
ai->ai_inode.i_ctime.tv_nsec = 0;
i_uid_write(&ai->ai_inode, (uid_t)be32_to_cpu(di->di_uid));
i_gid_write(&ai->ai_inode, (gid_t)be32_to_cpu(di->di_gid));
}