这篇是2年前写的东西,有不少需要改进的地方;暂且记录下来,在以后的文章中来改进之。:D
本文将从multiple devie driver的加载、卸载、ioctl系统调用的实现等线索,对md驱动中的具体实现加以讨论。
另外,本文将从md驱动中内核线程的使用方面进行一些讨论,借以从更加小粒度的地方了解md driver的具体实现。
在md.c的代码中,还涉及到md随系统启动的管理、与/proc文件系统的交互等等细节,在以下适当地地方将给出讨论。
本文所讨论的linux kernel为Redhat Linux AS 4.0 所使用的版本2.6.9。其中所涉及到的一些部分,可能和其他linux kernel版本中的md driver有所出入,请注意。
文中深红色加粗字体所表示的是对代码的注释,青色加粗的字体表示的是代码。
1 module加载、卸载
在module加载时,将调用md_init函数;在卸载时,将调用md_exit函数。md_init的原形如下:
int __init md_init(void)
{
……
if (register_blkdev(MAJOR_NR, "md"))/*register md block device. The major is number 9 with name 'md' have unpartitioned md arrays, one per minor number. */
return -1;
if ((mdp_major=register_blkdev(0, "mdp"))<=0) {
unregister_blkdev(MAJOR_NR, "md");
return -1;
}/*this sector register mdp device. The major is allocated dynamically with name 'mdp' and had on array for every 64 minors, allowing for upto 63 partitions.
devfs_mk_dir("md");/* Create a directory in the devfs namespace.*/
blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
md_probe, NULL, NULL);/*regist “md” device number renges*/
blk_register_region(MKDEV(mdp_major, 0), MAX_MD_DEVS<
/*blk_register_region() is under the gendisk interface*/
for (minor=0; minor < MAX_MD_DEVS; ++minor)
devfs_mk_bdev(MKDEV(MAJOR_NR, minor),
S_IFBLK|S_IRUSR|S_IWUSR,
"md/%d", minor);
/*create all devices under dir md*/
for (minor=0; minor < MAX_MD_DEVS; ++minor)
devfs_mk_bdev(MKDEV(mdp_major, minor<
S_IFBLK|S_IRUSR|S_IWUSR,
"md/d%d", minor);
/*create all devices under dir md*/
register_reboot_notifier(&md_notifier);/*register notifier of reboot or shutdown*/
raid_table_header = register_sysctl_table(raid_root_table, 1);
md_geninit();
return (0);
}
md_init在模块加载时注册md设备以及相关的系统调用接口。在Linux kernel 2.6.9中,md driver在加载时,注册两个主设备号(区别于Linux kernel 2.4中的使用一个主设备号),在以上代码注释中给出解释。
其中,md_geninit()主要注册md中/proc文件系统的接口,其原形如下:
static void md_geninit(void)
{
……
p = create_proc_entry("mdstat", S_IRUGO, NULL);/*register proc entry*/
if (p)
p->proc_fops = &md_seq_fops;/* set proc filesystem operator*/
}
在module卸载的时候调用md_exit函数,释放一些资源,其原形如下:
static __exit void md_exit(void)
与module加载时调用的md_init()函数对应,md_exit()函数解除md和mdp的注册、解除所有md设备在devfs中的注册、解除reboot notifier、解除系统调用接口和proc文件系统的接口。以上,没有在md_exit()的代码中给出注释,这些可以参照md_init()函数中的注释,对比来看。
2 ioctl系统调用
在m