20201306吴龙灿第十一章学习笔记
Ⅰ知识点归纳
前言
本章讨论EXT2文件系统。本章要引导读者实现一个与Linux系统完全兼容的EXT2文件系统。前提是,只要读者充分理解了一个文件系统,那么就可以轻松改编其他任何文件系统。
一、EXT2文件系统
EXT2文件系统是Linux系统中广泛使用的文件系统,该文件系统是一种索引式文件系统,它将分区分为inode和block,它会给每个文件分配一个inode,inode中存储文件的一些属性信息,block中存储文件真正的内容,一个block的大小有1k、4k等大小,一个block中只能存储一个文件,比如现在有一个文件占据了一个block的1B大小,那么这个block剩余的大小也无法分配给其他文件使用。大体存储结构如下图所示:

二、EXT2文件系统数据结构
(一)通过mkfs创建虚拟硬盘
在Linux下,命令:
Mke2fs [-b blksize -N ninodes] device nblocks
在设备上创建一个带有nblocks个块和ninodes个索引节点的EXT2文件系统。设备可以是真实设备,也可以是虚拟磁盘文件。如果未指定blksize,则默认块大小为1kb。如果未指定ninodes,mke2fs将根据nblocks计算一个默认的ninodes数。得到的EXT2文件系统可在Linux上使用。
举个例子:
dd if=/dev/zero of=vdisk bs=1024 count=1440
mke2fs vdisk 1440
可在一个名为vidsk的虚拟磁盘文件上创建一个EXT2文件系统,有1440个大小为1KB的块
(二)虚拟硬盘布局
因为一个分区可能很大,可能会分成很多很多个block,为了便于管理,系统将这些block分成多个block组,每个block组中存储当前组的信息和当前block组的block,如下图:

每个分区都有如下几个项目:
引导扇区:每个分区前的引导扇区
super block:超级块,它记录的是整个文件系统的信息,文件系统的类型,inode数量,block数量等,每个分区的super block是相同的
文件系统描述:描述每个block group 的开始与结束的block号码。
块对应表(block bitmap):用bit位记录了每一个block目前的状态,如果有数据就置为1,没有数据置为0。如果需要分配block,那么就找目前状态为0的。
inode 对应表(inode bitmap):和块对应表相似,记录的是inode的分配和未分配的号码。
inode table:详细记录了每一个inode的信息。
data block:详细记录文件数据的地方,每一个block都有block号码。
(三)超级块
在Linux操作系统中,每个文件系统都必须有一个超级块。所谓超级块不是普通的块,而是不一样的块,其英文为superblock。
EXT2文件系统自然也不例外,在该文件系统开头的地方也有一个超级块,具体如图所示。EXT2文件系统的超级块位于磁盘开始偏移1kb的地方,其尾部却与4kb对齐。

EXT2文件系统的超级块是对文件系统整体属性的描述,包括文件系统inode总量、磁盘块总量、inode使用情况、文件系统特性和挂载时间等等。
下面说明了超级块结构中的一些重要字段:

(四)EXT2的索引节点
在一个实际分立式目录的文件系统中,索引节点(inode)主要需要两部分内容来支持:一是inode结构;二是对于节点的操作函数。
Ext2的每个文件(或目录)都有唯一的i节点ext2_inode,它保存了一个文件所有与存储有关的属性。
Linux在文件include/linux/ext2_fs.h中定义的i节点结构ext2_inode如下:
struct ext2_inode {
__le16 i_mode; /* 文件模式 */
__le16 i_uid; /* 文件拥有者uid的低16位 */
__le32 i_size; /* 文件大小 */
__le32 i_atime; /* 最后访问时间 */
__le32 i_ctime; /* 创建时间 */
__le32 i_mtime; /* 修改时间 */
__le32 i_dtime; /* 删除时间 */
__le16 i_gid; /* 块组id的低16位 */
__le16 i_links_count; /* 链接计数,即文件别名的数目 */
__le32 i_blocks; /* 文件占用的存储块数 */
__le32 i_flags; /* 标志 */
union {
struct {
__le32 l_i_reserved1;
} linux1;
struct {
__le32 h_i_translator;
} hurd1;
struct {
__le32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__le32 i_block[EXT2_N_BLOCKS];/* 文件索引表 */
__le32 i_generation; /* File version (for NFS) */
__le32 i_file_acl; /* File ACL */
__le32 i_dir_acl; /* Directory ACL */
__le32 i_faddr; /* 碎片地址 */
union {
struct {
__u8 l_i_frag; /* 碎片数目 */
__u8 l_i_fsize; /* 碎片大小 */
__u16 i_pad1;
__le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* 碎片数目 */
__u8 h_i_fsize; /* 碎片大小 */
__le16 h_i_mode_high;
__le16 h_i_uid_high;
__le16 h_i_gid_high;
__le32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* 碎片数目 */
__u8 m_i_fsize; /* 碎片大小 */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* 与操作系统相关的数据 */
};
其中,最重要的成员i_mode和指针i_block[]。i_mode指定文件类型;而指针数组i_block[]则是文件索引表。
i_block[]指针数组的示意图如下:

i_block[]共有15项,其中前12项为直接指向文件数据块的指针,后3项分别为采用多级索引结构的“一次间接指针”、“二次间接指针”和“三次间接指针”。其作用与内存管理中的多级页表类似,便于大型文件的存储处理。
三、mkdir命令
mkdir是make directory的缩写,Linux中 mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录。
1.语法:
mkdir [选项] 目录名称
2.功能:
通过 mkdir 命令可以实现在指定位置创建以 指定的文件名 命名的文件夹或目录。要创建文件夹或目录的用户必须对所创建的文件夹的父文件夹具有写权限。并且所创建的文件夹(目录)不能与其父目录(即父文件夹)中的文件名重名,即同一个目录下不能有同名的(区分大小写)。还可以设置目录的权限。
文件或目录的权限又分为3种:只读、只写、可执行。
| 权限 | 权限数值 | 二进制 | 具体作用 |
|---|---|---|---|
| r | 4 | 00000100 | read,读取。当前用户可以读取文件内容,当前用户可以浏览目录。 |
| w | 2 | 00000010 | write,写入。当前用户可以新增或修改文件内容,当前用户可以删除、移动目录或目录内文件。 |
| x | 1 | 00000001 | execute,执行。当前用户可以执行文件,当前用户可以进入目录。 |
依照上面的表格,权限组合就是对应权限值求和,如下:
7 = 4 + 2 + 1 读写运行权限
5 = 4 + 1 读和运行权限
4 = 4 只读权限
3.参数:
-m<目录属性>或--mode<目录属性> 建立目录时同时设置目录的权限。类似chmod,而不是rwxrwxrwx 减umask。
-p或--parents 若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多个目录,即使这些目录已存在也不当作错误处理。
-v或--verbose 每次创建新目录时显示详细的信息。
-Z或--context=CTX 将每个创建的目录的SELinux 安全环境设置为CTX。
--help 在线帮助。查看该命令功能和可带参数等。
Ⅱ最有收获的内容
在第七章的学习中,我已经接触了EXT2文件系统,已经对这一内容有了初步的掌握。但是学习了第十一章,我发现需要进一步深究的东西还有很多。下面我就说一下我最感兴趣的地方,以及在这个地方我自己的理解。
在虚拟磁盘布局这一小节内容我理解很深刻,我通过查资料,发现了虚拟布局的各部分以及各部分的作用。上面已经提到一部分,我主要说一下布局的核心部分inndes块。
linux 系统中每个文件包括内容数据和文件属性两部分,这两部分分开来存储,文件内容存在块中,文件属性存在inode中。当分区被初始化为ext2文件系统时,它一定会有inode表和块区域这两个区域。inode记录文件的属性,以及文件内容放在哪个块中。这些属性包括:
该文件的存取模式(read/write/excute);
该文件的拥有者与群组(owner/group);
该文件的容量;
该文件创建或状态改变的时间(ctime);
最近一次的读取时间(atime);
最近修改的时间(mtime);
定义文件特性的旗标(flag),如 SetUID...;
该文件真正内容的指向 (pointer);

Ⅲ问题
在Linux系统,怎么样在命令行中展示超级块?
Ⅳ解决思路
通过查阅资料,了解了对超级块的一些操作:
对超级块进行操作(创建,读取,释放)
get_super, put_super, read_super
文件系统加载/卸载:
mount/umount sys_mount, sys_umount
根文件系统的加载
(/)mount_root
还知道了用c程序显示EXT2文件系统的超级块信息:
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<ext2fx/ext2_fs.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef struct ext2_super_block SUPER;
SUPER *sp;
char buf[1024];
int fd,blksize,inodesize;
int printf(char *s,u32 x)
{
printf("%-30s=%8d\n",s,x);
}
int super(char *device)
{
fd=open(device,O_RDONLY);
if(fd<0){
printf("open %sfailed\n",device);exit(1);
}
lseek(fd,(long)1024*1,0);
read(fd,buf,1024);
sp=(SUPER *)buf;
printf("%-30s=%8x","s_magic",sp->s_magic);
if(sp->s_magic!=0xEF53){
printf("NOT an EXT2 FS\n");exit(2);
}
printf("EXT2 FS OK\n");
printf("s_inodes_count",sp->s_inodes_count);
printf("s_blocks_count",sp->s_blocks_count);
printf("s_r_blocks_count",sp->s_r_blocks_count);
printf("s_free_inodes_count",sp->s_free_inodes_count);
printf("s_free_blocks_count",sp->s_free_blocks_count);
printf("s_first_data_block",sp->s_first_data_block);
printf("s_log_block_size",sp->s_log_block_size);
printf("s_blocks_per_group",sp->s_blocks_per_group);
printf("s_inodes_per_group",sp->s_inodes_per_group);
printf("s_mnt_count",sp->s_mnt_count);
printf("s_max_mnt_count",sp->s_max_mnt_count);
printf("%-30s=%8x\n","s_magic",sp->s_magic);
printf("s_mtime=%s",ctime(&sp->s_mtime));
printf("s_wtime=%s",ctime(&sp->s_wtime));
blksize=1204*(1<<sp->s_log_block_size);
printf("block size = %d\n",blksize);
printf("inode size = %d\n",sp->s_inode_size);
}
char *device="mydisk";
int main(int argc, char *argv[])
{
if(argc>1)
device=argv[1];
super(device);
}
Ⅴ实践内容、代码链接与截图
一、通过mkfs创建虚拟磁盘

二、挂载文件系统之后解析文件系统
wlc@wlc-VirtualBox:~$ dumpe2fs /dev/loop0通过此命令实现:

三、mkdir命令操作
1.创建一个空目录
命令:mkdir test
2.递归创建多个目录
命令:mkdir -p test2/test22
3.创建权限为777的目录
命令:mkdir -m 777 test3
4.创建新目录都显示信息
命令:mkdir -v test4
5.一个命令创建项目的目录结构
命令:mkdir-vpscf/{lib/,bin/,doc/{info,product},logs/{info,product},service/deploy/{info,product}}
实践结果:


浙公网安备 33010602011771号