linux内核奇遇记之md源代码解读之二

linux内核奇遇记之md源代码解读之二
转载请注明出处:http://blog.csdn.net/liumangxiong
在编译完成linux内核源代码的时候,drivers/md目录下会生成多个ko文件,那么这些内核模块哪一个先加载,哪一个后加载的呢?例如md-mod.ko, raid5.ko, raid10.ko,这些模块是一起加载的呢,还是有先后顺序呢?如果熟悉linux内核编程的话,知道有一个request_module函数,这个函数用于请求加载一个模块,但这个函数并不能说明一个模块对另一个模块的依赖关系。准确的信息还是来自于Kconfig,这里只抽取Kconfig中相关的部分:
config BLK_DEV_MD
     tristate "RAID support"
config MD_RAID10
     tristate "RAID-10 (mirrored striping) mode"
     depends on BLK_DEV_MD
config MD_RAID456
     tristate "RAID-4/RAID-5/RAID-6 mode"
     depends on BLK_DEV_MD
从这里我们可以看出,raid5.ko, raid10.ko都是依赖于md-mod.ko的,这就决定了我们的阅读方向是从md-mod.ko中开始的。
那么md-mod.ko中又是从哪个文件开始的呢?这就要找module_init函数,这个函数在md.c中定义的,那么就从这里入手。
8416 static int __init md_init(void)
8417 {
8418         int ret = -ENOMEM;
8419 
8420         md_wq = alloc_workqueue("md", WQ_MEM_RECLAIM, 0);
8421         if (!md_wq)
8422                 goto err_wq;
8423 
8424         md_misc_wq = alloc_workqueue("md_misc", 0, 0);
8425         if (!md_misc_wq)
8426                 goto err_misc_wq;
8427 
8428         if ((ret = register_blkdev(MD_MAJOR, "md")) < 0)
8429                 goto err_md;
8430 
8431         if ((ret = register_blkdev(0, "mdp")) < 0)
8432                 goto err_mdp;
8433         mdp_major = ret;
8434 
8435         blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE,
8436                             md_probe, NULL, NULL);
8437         blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE,
8438                             md_probe, NULL, NULL);
8439 
8440         register_reboot_notifier(&md_notifier);
8441         raid_table_header = register_sysctl_table(raid_root_table);
8442 
8443         md_geninit();
8444         return 0;
8445 
8446 err_mdp:
8447         unregister_blkdev(MD_MAJOR, "md");
8448 err_md:
8449         destroy_workqueue(md_misc_wq);
8450 err_misc_wq:
8451         destroy_workqueue(md_wq);
8452 err_wq:
8453         return ret;
8454 }
模块的初始化过程看起来异常地简单,这就像有些人表面看起来十分普通,内心里却无比地强大,所以不要只看外表,还要听其言观其行。内在的美丽比外表的荣华更具吸引力和持久性。
8420和8424行,分别创建了工作队列,md_wq是用于flush命令的,另一个md_misc_wq,misc是miscellaneous的简写,是杂项的意思,用于处理一些零零碎碎的事情。
8428和8431行,创建了两个块设备,刚开始我只注意md的设备,压根没在意mdp,搜索变量mdp_major,在函数autorun_devices中使用了这个变量:
5474                 if (part) {
5475                         dev = MKDEV(mdp_major,
5476                                     rdev0->preferred_minor << MdpMinorShift);
5477                         unit = MINOR(dev) >> MdpMinorShift;
5478                 } else {
5479                         dev = MKDEV(MD_MAJOR, rdev0->preferred_minor);
5480                         unit = MINOR(dev);
5481                 }
5474行,变量part是函数传入参数,表示磁盘第几个分区,那么就知道mdp_major中字母p是表示part的意思,而mdp_major就表示用磁盘分区创建的阵列。
8435和8437行,创建了两个region,这两个函数的作用是在用户态创建了一个/dev/md*设备时,内核态就会对应调用md_probe创建一个mddev结构体,之后在用户态对/dev/md*的操作到内核态就相应地对mddev的操作了。
8440行,注册关机回调函数,主要作用是停止阵列线程,刷数据操作。
8441行,注册sysctl函数,用于控制阵列最小和最大的sync速度。
8443行,注册proc函数,于是有了目录/proc/mdstat,该目录的显示由函数md_seq_show控制。
md初始化代码就这样轻松地完成了,可是回到我们的初衷,仍然对md设备一无所知。那么md设备是如何创建的呢?创建的过程又是怎么的呢?一个阵列拥有哪些资源?下一节我们直入核心,开始阅读阵列创建的过程。
转载请注明出处:http://blog.csdn.net/liumangxiong
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: MDLinux内核中的一个模块,可实现磁盘阵列的软件级RAID,它和RAID0、RAID1、RAID4、RAID5、RAID6一样,就是一种磁盘阵列方案。 MD中最主要的部分是驱动程序,它运行在内核态中。它将多个磁盘设备组合在一起,成为一个逻辑设备,该逻辑设备对应着一个块设备文件。在这个逻辑设备上,可实现磁盘阵列的软件级RAID功能。 MD驱动程序的主要源代码是在/drivers/md目录下的md.c文件中,它包括了MD的全部源代码,还有一些其他相关文件,比如raid5.c等。 在这个文件中,最值得学习的是内核的模块化编程思想。模块化编程是一种将代码划分为模块的软件设计方法,通过将代码划分为不同的模块,实现代码的解耦、可重用、可维护性等目标。 在MD.c中我们还可以看到内核中的锁、内存管理等基本的内核技术的应用。通过对MD.c进行源代码解读,能够深入了解Linux内核的实现原理,特别是MD的RAID功能的实现,对于我们进一步学习Linux内核的相关知识和对其进行应用开发具有很大的帮助。 总之,通过对MD.c源代码解读,我们可以学习到Linux内核模块化编程思想、内存管理、锁机制等基本内核技术,进一步掌握Linux内核的实现原理,从而在Linux应用开发中更加熟练娴熟。 ### 回答2: MD(Multiple Devices)是一种常用的软件RAID方案,可以在Linux内核中实现,同时也是Linux内核中最基本的RAID模式之一。MD在实现中使用了驱动程序和用户空间工具,其中驱动程序包含在内核中,因此我们需要对MD源代码进行解读MD源代码是由C语言编写的,主要包含在drivers/md/目录下。在这个目录下,可以看到一些重要的文件和子目录,例如md.c、md.h、raid1.c、raid5.c等。这些文件和子目录定义了MD的基本结构和函数,如磁盘阵列的基本信息结构、磁盘块的操作函数等。 MD的实现思路比较清晰,可以简单地理解为将多个物理磁盘组合在一起,形成一个虚拟的块设备。在这个虚拟的块设备上,可以进行读写等操作,而具体的数据操作则由MD提供的不同RAID模式实现。例如,MD支持的RAID1模式就是将数据同步写入两个物理磁盘,以实现磁盘容错。而MD支持的RAID5模式则是将数据分散写入多个物理磁盘,通过奇偶校验等方式实现磁盘容错。 在MD源代码解读过程中,需要重点关注这些RAID模式的实现方式和相关函数。同时,还需要了解整个MD的插入和移除机制、数据恢复机制等,以便更好地理解和修改MD源代码。 总之,对于想要深入了解Linux内核中RAID相关实现的开发者来说,对MD源代码进行解读是一个非常有价值的学习和探索过程。 ### 回答3: mdlinux内核中的一个重要模块,支持多种存储设备,包括硬盘、闪存和网络存储等。如果想要深入了解linux内核的运行机制,就必须掌握md源代码。下面就对md源代码进行解读md源代码的核心是md.c文件。这个文件中定义了md模块的核心函数,包括md_init()、md_run()和md_stop()等。其中md_init()函数主要负责初始化md模块的各个子系统,包括raid核心、hotplugging、proc文件系统和sysfs文件系统等。md_run()函数则是md模块的主要循环,负责轮询设备状态并执行相应的IO操作。md_stop()函数则是md模块的关闭函数,用于释放模块占用的各种资源。 除了md.c文件外,md模块的代码还包括一些关键性质的文件,例如mddev.c、md.h和md_u.h等。其中,mddev.c文件定义了md设备的数据结构,包括磁盘阵列、线性设备和伪设备等。md.h和md_u.h文件则分别定义了用户空间和内核空间的md控制接口,包括创建和删除设备、添加和删除磁盘等。 在理解md源代码时需要注意的是,md模块涉及到多个子系统,包括块设备、文件系统和RAID等,因此需要对这些子系统的工作原理和相互关系有清晰的理解。同时,由于md模块的代码相当复杂,需要仔细地阅读和调试,才能完成内核的定制和优化工作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值