Linux的ROMFS代码分析
以下是我自己第一次接触源代码时自己加的,仅供参考,应该有很多漏洞的,希望高人指点啊
#include <linux/module.h> //加载内核模块
#include <linux/types.h>
#include <linux/errno.h>//定义Linux些出错码的常量符号库
#include <linux/slab.h>//动态分配和释放
#include <linux/romfs_fs.h> //只读文件库
#include <linux/fs.h> //文件库
#include <linux/locks.h>//提供锁定和强制锁定的支持
#include <linux/init.h>//初始化
#include <linux/smp_lock.h>//同步信号锁
#include <asm/uaccess.h>//符号连接
static __s32//不用s32是为了防止污染用户的命名空间,好像用s32还要有什么文件的引入的,还是不很明白
romfs_checksum(void *data, int size)//校验文件数据
{ //checksum是前512字节的校验和,用于确认整个文件系统结构数据的正确性
__s32 sum, *ptr; //定义一个指针指向数据
sum = 0; ptr = data;
size>>=2;
while (size>0) { //读文件
sum += ntohl(*ptr++);//指针自加,向下查找
//ntohl将一个无符号长整形从网络字节顺序转换为主机字节顺序
size--;//剩余大小减小
}
return sum; //返回校验和
}
//声明超级操作结构
static struct super_operations romfs_ops;
static struct super_block * //超级块——记录文件的管理信息
romfs_read_super(struct super_block *s, void *data, int silent)
{
struct buffer_head *bh; /
kdev_t dev = s->s_dev; //Linux内核采用的另一种不同的资料型别,//指向超级块所在的设备号
struct romfs_super_block *rsb;//此处定义一个指向文件超级块的全局指针
int sz;
set_blocksize(dev, ROMBSIZE); //设置超级块的大小
s->s_blocksize = ROMBSIZE; //块大小
s->s_blocksize_bits = ROMBSBITS;//块大小的字节数
s->u.generic_sbp = (void *) 0;/
s->s_maxbytes = 0xFFFFFFFF;//最大字节数
bh = sb_bread(s, 0);//读/dev/sdbx当前扩展区或主分区的0区块
if (!bh) { //缓冲头指针无效
printk ("romfs: unable to read superblock\n");
goto outnobh;//执行outnobh操作
}
rsb = (struct romfs_super_block *)bh->b_data; //读取文件
sz = ntohl(rsb->size);//获取数据项在主机中的顺序,将该值赋给sz,此处可以理解为该数据项的大小
//该数据项为ROMFS的首部,表述的是ROMFS超级块的信息,操作系统通过其来识别文件类型
//此处的功能就相当于,判别文件的卷名
if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1//word0和word1在内核中定义为-rom1fs-
|| sz < ROMFH_SIZE) { //文件类型不是只读或数据的大小小于4bits,即能被16整除,#define ROMFH_SIZE 16
if (!silent)//则在设备中找不到该只读文件,只有silent不为0是才不显示找不到这条报错语句
//silent在上面并没有初始化,所以随机应该为负的,!silent就是正的,就是执行以下语句,可是有什么意义?
//表明在设备中找不到,如果不输出此语句就表示有可能已经在设备中找到,只是不能匹配所以不能读出?
printk ("VFS: Can't find a romfs filesystem on dev "
"%s.\n", kdevname(dev));
goto out;//执行out操作
}//初步匹配成功,进一步检测第sz到第512个字节文件数据,否则无需进行接下来的校验,可以节省时间和资源
if (romfs_checksum(rsb, min_t(int, sz, 512))) {//调用romfs_checksum()检测失败,则报错
printk ("romfs: bad initial checksum on dev "
"%s.\n", kdevname(dev));//检测失败,则报错
goto out;//执行out操作,表示通过检测,读取超级块成功,释放缓冲区允许其他操作
}
//到此为止,已经完成了文件首部的检验
//进一步检测失败,需要调整超级块
s->s_magic = ROMFS_MAGIC; //表明是romfs类型
//s_magic记录了从设备中读取的标识号,以便确认从设备上的数据与涉及的文件系统相符
s->u.romfs_sb.s_maxsize = sz;//只读文件系统超级块的最大值
s->s_flags |= MS_RDONLY;//设置了MS_RDONLY类型的文件只以只读的形式装载,不允许写入,也不会进行间接修改
//s_flags是一个标识列表,这些标志与各个信息节点中的标志进行逻辑或操作,一确定某种行为
//找文件系统的开始处,再次运用sz变量只是此时不再表示数据项的大小,而是表示开始读取的位置
sz = (ROMFH_SIZE +//#define ROMFH_PAD (ROMFH_SIZE-1) #define ROMFS_MAXFN (~ROMFH_PAD)
strnlen(rsb->name, ROMFS_MAXFN) + 1 + ROMFH_PAD)
& ROMFH_MASK;
//完成读取非规范文件(不可读取)后的初步“恢复”操作
brelse(bh);//释放缓冲区,等待该缓冲区解锁,引用计数减1,唤醒等待空闲缓冲区的进程
//尝试为超级块分配新的目录
s->s_op = &romfs_ops;//给超级块对象的操作表赋值
s->s_root = d_alloc_root(iget(s, sz));/
if (!s->s_root)//找不到根目录,即分配目录项失败
goto outnobh;//执行outnobh将指针指控,方便下次使用
if (0) {//0,不就是永远不执行这些语句?难道只是为了做操作声明?
out:
brelse(bh);//释放缓冲区
outnobh:
s = NULL;//找不到根目录,指针指向随机,此时应将将指针置空
}
return s;//返回超级块指针,方便后面的操作
}