在《深入Linux设备驱动程序内核机制》第11章"块设备驱动程序” 11.2节当中给出了ramdisk的两个版本的实现,这个示例的目的除了让读者直观感受一下编写一个块设备驱动程序的大体框架和关键元素之外,还特别提到“这个例子还有一个非常重要的潜在用途,那就是通过ramdisk来研究Linux的文件系统,比如ext3等,因为mkfs.ext3工具会将ext3文件系统做到这个ramdisk中,这意味着ext文件系统家族的超级块、组描述符、数据位图、inode位图和inode表等一系列的重量级数据结构会被记录到ramdisk中,我们可以通过另外的方式去读/写这段RAM空间来获得现场的数据,这对理解Linux中ext文件系统家族的源代码是非常有帮助的...”,当时因为书的进度以及考虑到文件系统方面的内容跟书的主题并没有直接的关联,所以并没有做实际的尝试。。。
最近我在ramdisk的源码基础上将sdisk变量给export了出来:
- 01.char *sdisk[RAMHD_MAX_DEVICE] = {NULL,};
- 02.EXPORT_SYMBOL_GPL(sdisk);
然后又重新写了另一个内核模块ram_ext3,在这个模块中我会利用前面那个ramdisk模块导出的sdisk变量来获得ramdisk上ext3文件系统的超级块等数据,因为时间的关系我只做了个原型,在ram_ext3模块的初始化函数中打印ext3 super block的一些数据,尤其是其中的s_magic成员(EXT3_SUPER_MAGIC = 0xEF53),这样可以验证所读出的数据是否是我们所需要的东西。如果读者对ext3的内核源码感兴趣,可以在ram_ext3的基础上进行扩展,以方便观察在某些文件操作之后ext3系统中数据的变化。
这个示例的操作步骤我简单描述一下:
1. 将ramdisk内核模块加入系统 insmod ramhd_mkreq.ko,成功之后将在/dev目录下产生两个设备文件节点/dev/ramhda和/dev/ramhdb
2. 我只使用其中的/dev/ramhda,在上面用mkfs.ext3命令生成ext3文件系统,命令输出截屏如下(点击放大):
3. 步骤2中的输出当中有几个重要的数据: Block size = 1024, First data block=1,所以ext3的文件系统super block放置在第一个block上,换句话说是sdisk[0]所在地址再加上1024才是ext3文件系统的数据,所以ram_ext3内核模块初始化函数得做如下处理 ---
- 01.extern char *sdisk[2];
- 02.static int __init ramext3_init(void)
- 03.{
- 04. //EXT3_SUPER_MAGIC = 0xEF53
- 05. struct ext3_super_block *sb;
- 06. unsigned long tmp = (unsigned long)sdisk[0];
- 07. tmp += 1024;
- 08.
- 09. sb = (struct ext3_super_block *)tmp;
- 10. //printk("sdisk = %p\n", sdisk[0]);
- 11. printk("s_magic = 0x%X, s_inodes=%d, s_blocks=%d\n", sb->s_magic, sb->s_inodes_count, sb->s_blocks_count);
- 12. printk("s_blocks_per_group = %d, s_log_frag_size=%d, s_inodes_per_group=%d\n", sb->s_blocks_per_group, sb->s_log_frag_size, sb->s_inodes_per_group);
- 13. return 0;
- 14.}
4. 把ram_ext3.ko加入系统 insmod ram_ext3.ko,然后看到dmsg的输出截屏如下(点击放大):
可以看到文件magic值为s_magic = 0xEF53, inode数量是s_inodes=2048, block块数量是s_blocks=8192,...,这些数据都与我们当初在/dev/ramhda上创建ext3时mkfs.ext3工具所输出的数据相吻合。
对ext3感兴趣的同学可以继续利用这里的试验去挖掘自己所需要的东西。最后我将ramdisk和ram_ext3内核模块的源码作为附件放在这里。。。
(原文首发于)
阅读(383) | 评论(0) | 转发(0) |