Linux 内核中MD及RAID模块化
这段时间接触了下linux内核中的MD代码以及RAID源码,想自己在上面加一些东西,期间就要重新编译MD和RAID,但是由于修改的是内核源码,所以刚开始每次编译都需要编译内核,花费的时间比较长,于是就想起了将MD和RAID进行模块化,这样的话就大大节省了编译的时间,下面我们就来谈谈是怎么模块化的。
模块化的步骤大致分为三个阶段:编译内核、编译模块和插入模块。接下来逐一讲下这三个阶段。
编译内核
首先确定你想编译的linux内核版本,然后下载源码,我用的是linux 4.0.2的版本。下载完源码后,解压,并进入该目录,切换到root权限并执行make menuconfig
命令,会出现如下界面:
选择Device Drivers,进入如下界面:
选择*Multiple devices driver support(RAID and LVM),进入MD的模块设置界面:
这里每一项的前面<>里有两个选项‘M’和‘*’,忽略空的情况。‘M’表示编译内核时将这一项编译成模块,以后可以自行编译插入到内核中,而无需再重新编译内核;’*’表示编译内核时将这项嵌入到内核中,以后再修改时,必须重新编译内核。所以这里对所有的条目能选’M’的都选’M’,不能选’M’的全打’*’。
注意:在 make menuconfig
时有可能出现error,那是缺少相应的依赖条件,可执行 apt-get install libncurses5-dev libncursesw5-dev
,然后再 make menuconfig
即可。
接下来一次执行如下命令即可:
- make -j4
- make modules_install -j4
- make install -j4
- reboot
至此,内核编译完毕,开始可使用 uname -r
来查看当前内核版本。
编译模块
此时进入drivers/md/目录下,需要修改Makefile文件内容以实现模块化编译。
原先的Makefile内容如下:
old-Makefile
# Makefile for the kernel software RAID and LVM drivers.
#
dm-mod-y += dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o dm-stats.o
dm-multipath-y += dm-path-selector.o dm-mpath.o
dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \
dm-snap-persistent.o
dm-mirror-y += dm-raid1.o
dm-log-userspace-y \
+= dm-log-userspace-base.o dm-log-userspace-transfer.o
dm-thin-pool-y += dm-thin.o dm-thin-metadata.o
dm-cache-y += dm-cache-target.o dm-cache-metadata.o dm-cache-policy.o
dm-cache-mq-y += dm-cache-policy-mq.o
dm-cache-cleaner-y += dm-cache-policy-cleaner.o
dm-era-y += dm-era-target.o
md-mod-y += md.o bitmap.o
raid456-y += raid5.o
# Note: link order is important. All raid personalities
# and must come before md.o, as they each initialise
# themselves, and md.o may use the personalities when it
# auto-initialised.
obj-$(CONFIG_MD_LINEAR) += linear.o
obj-$(CONFIG_MD_RAID0) += raid0.o
obj-$(CONFIG_MD_RAID1) += raid1.o
obj-$(CONFIG_MD_RAID10) += raid10.o
obj-$(CONFIG_MD_RAID456) += raid456.o
obj-$(CONFIG_MD_MULTIPATH) += multipath.o
obj-$(CONFIG_MD_FAULTY) += faulty.o
obj-$(CONFIG_BCACHE) += bcache/
obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.o
obj-$(CONFIG_DM_BUFIO) += dm-bufio.o
obj-$(CONFIG_DM_BIO_PRISON) += dm-bio-prison.o
obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY) += dm-delay.o
obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o
obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o
obj-$(CONFIG_DM_SWITCH) += dm-switch.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_PERSISTENT_DATA) += persistent-data/
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
obj-$(CONFIG_DM_RAID) += dm-raid.o
obj-$(CONFIG_DM_THIN_PROVISIONING) += dm-thin-pool.o
obj-$(CONFIG_DM_VERITY) += dm-verity.o
obj-$(CONFIG_DM_CACHE) += dm-cache.o
obj-$(CONFIG_DM_CACHE_MQ) += dm-cache-mq.o
obj-$(CONFIG_DM_CACHE_CLEANER) += dm-cache-cleaner.o
obj-$(CONFIG_DM_ERA) += dm-era.o
ifeq ($(CONFIG_DM_UEVENT),y)
dm-mod-objs += dm-uevent.o
endif
修改为如下内容:
new-makefile
LINUXROOT=/lib/modules/$(shell uname -r)/build
all:
make -C $(LINUXROOT) SUBDIRS=`pwd` $(EXTRA_CFLAGS) KBUILD_VERBOSE=1 modules
obj-m += raid1.o
obj-m += raid10.o
obj-m += raid456.o
obj-m += md-mod.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o
再进行 make
产生md-mod.ko 和 raid456.ko文件(以raid5为例)。至此编译结束。
插入模块
首先插入md模块: insmod md-mod.ko
在插入raid456模块: insmod raid456.ko
却出现如下错误:Error: could not insert module raid456.ko: Unknown symbol in module,原因是缺少依赖关系,可以用modprobe来自动补齐其依赖模块,命令为 modprobe raid456
,使用modprobe时,后面那个raid456一定不能写成raid456.ko!
至此插入模块也已经搞定啦,可以使用 lsmod
来查看系统的所有模块。接下来就可以按自己的想法来修改内核代码了,比如说修改raid5的源码创建新的raid51等等之类的,嘻嘻^_^~
- 使用mdadm创建 ↩