一、問題描述 本項目的內(nèi)容是要添加一個類似于ext2的自定義文件系統(tǒng)xs_ext2,。我們對xs_ext2文件系統(tǒng)的描述如下: 1,、xs_ext2文件系統(tǒng)的物理格式定義與ext2基本一致,除了xs_ext2的magic number是0x6666,,而ext2的magic number是0xEF53,。 2、xs_ext2是ext2的定制版本,,它只支持原來ext2文件系統(tǒng)的部分操作,,以及修改了部分操作,。 文件系統(tǒng)的定義和操作是完成了,但不要忘了,,這樣的一個文件系統(tǒng)如何去創(chuàng)建呢,?我們最后還要提供一個創(chuàng)建xs_ext2文件系統(tǒng)的工具:mkfs.xs_ext2。 如何實現(xiàn)上面提出來的要求呢,?首先從添加一個完全和ext2相同的xs_ext2開始,,然后再對xs_ext2進行雕琢,,逐步達到上一小節(jié)提到的要 求:先修改magic number,再修改Linux對xs_ext2文件系統(tǒng)的一些操作,。最后是創(chuàng)建文件系統(tǒng)的工具mkfs.xs_ext2的完成,。 1. 添加一個和ext2完全相同的文件系統(tǒng)xs_ext2 要添加一個與ext2完全相同的文件系統(tǒng)xs_ext2,首先是確定實現(xiàn)ext2文件系統(tǒng)的內(nèi)核源碼是由哪些文件組成,。Linux源代碼結構很清楚 地告訴我們:fs/ext2目錄下的所有文件是屬于ext2文件系統(tǒng)的,。再檢查一下這些文件所包含的頭文件,可以初步總結出來Linux源代碼中屬于 ext2文件系統(tǒng)的有: fs/ext2/balloc.c fs/ext2/bitmap.c fs/ext2/dir.c fs/ext2/file.c fs/ext2/fsync.c fs/ext2/ialloc.c fs/ext2/inode.c fs/ext2/ioctl.c fs/ext2/namei.c fs/ext2/super.c fs/ext2/symlink.c include/linux/ext2_fs.h include/linux/ext2_fs_i.h include/linux/ext2_fs_sb.h 有了這些初步的信息后(當然這些信息是否正確,,還需后面的檢驗),,我們接下來開始添加xs_ext2文件系統(tǒng)的源代碼到Linux源代碼。 由于本節(jié)工作是要克隆ext2文件系統(tǒng)到xs_ext2文件系統(tǒng),,所以我們需要把ext2部分的源代碼克隆到xs_ext2去,,即復制一份以上所列 的ext2源代碼文件給xs_ext2用。按照Linux源代碼的組織結構,,我們把xs_ext2文件系統(tǒng)的源代碼存放到fs/xs_ext2下,,頭文件 放到include/linux下。在Linux的shell下,,執(zhí)行如下操作: #cd /usr/src/linux #cd fs #cp –R ext2 xs_ext2 #cd ../include/linux #cp ext2_fs.h xs_ext2_fs.h #cp ext2_fs_i.h xs_ext2_fs_i.h /*2.6 nernel 沒有這個文件*/ #cp ext2_fs_sb.h xs_ext2_fs_sb.h 這樣就完成了克隆文件系統(tǒng)工作的第一步——源代碼復制,。對于克隆文件系統(tǒng)來說,這樣當然還遠遠不夠,,因為文件里面的數(shù)據(jù)結構名,、函數(shù)名、以及相關的一些宏等內(nèi)容還沒有根據(jù)xs_ext2改掉,,連編譯都通不過,。 下面我們開始克隆文件系統(tǒng)的第二步:修改上面添加的文件的內(nèi)容。為了簡單起見,,我們做了一個最簡單的替換:將原來*EXT2*替換成*XS_EXT2*,;將原來的*ext2*替換成*xs_ext2*。 例如,, ---linux/include/linux/xs_ext2_fs.h.orig +++linux/include/linux/xs_ext2_fs.h …… *************** *** 65,76 **** /* First non-reserved inode for old ext2 filesystems */ -#define EXT2_GOOD_OLD_FIRST_INO 11 +#define XS_EXT2_GOOD_OLD_FIRST_INO 11 /* * The second extended file system magic number */ -#define EXT2_SUPER_MAGIC 0xEF53 +#define XS_EXT2_SUPER_MAGIC 0xEF53 /* * Maximal count of links to a file */ -#define EXT2_LINK_MAX 32000 +#define XS_EXT2_LINK_MAX 32000 …… *************** *** 217,217 **** -struct ext2_inode { +struct xs_ext2_inode { …… 再如: ---linux/fs/xs_ext2/namei.c.orig +++linux/fs/xs_ext2/namei.c …… *************** *** 95,107 **** -static int ext2_create (struct inode * dir, struct dentry * dentry, int mode) +static int xs_ext2_create (struct inode * dir, struct dentry * dentry, int mode) { - struct inode * inode = ext2_new_inode (dir, mode); + struct inode * inode = xs_ext2_new_inode (dir, mode); int err = PTR_ERR(inode); if (!IS_ERR(inode)) { - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; + inode->i_op = &xs_ext2_file_inode_operations; + inode->i_fop = &xs_ext2_file_operations; + inode->i_mapping->a_ops = &xs_ext2_aops; mark_inode_dirty(inode); - err = ext2_add_nondir(dentry, inode); + err = xs_ext2_add_nondir(dentry, inode); } return err; } …… 其它代碼的修改類似,。 修改方法: 把substitute.sh文件拷貝到/usr/src/linux/fs/xs_ext2目錄下 文件內(nèi)容如下: #!/bin/sh SCRIPT=substitute.sh for f in *; do if [ $f = $SCRIPT ]; then echo "skip $f" continue fi echo -n "substitute ext2 to myext2 in $f..." cat $f | sed 's/ext2/myext2/g' > ${f}_tmp mv ${f}_tmp $f echo "done" echo -n "substitute EXT2 to MYEXT2 in $f..." cat $f | sed 's/EXT2/MYEXT2/g' > ${f}_tmp mv ${f}_tmp $f echo "done" done #chmod 777 substitue.sh 然后到/usr/src/linux/include/linux目錄下,,找到3個文件 include/linux/ext2_fs.h include/linux/ext2_fs_i.h include/linux/ext2_fs_sb.h 執(zhí)行 %s/ext2/xs_ext2/gc %s/EXT2/XS_EXT2/gc 以上文件修改完畢 關于具體文件系統(tǒng)部分的代碼是修改完了,但是關于具體文件系統(tǒng)和整個操作系統(tǒng)的接口部分是不是也需要修改呢,?根據(jù)前面所學的內(nèi)容,,想起來我們還需要 修改操作系統(tǒng)中所有文件系統(tǒng)都需要的兩個數(shù)據(jù)結構:struct super_block和struct inode。Linux要支持的文件系統(tǒng),,必須在這兩個結構中的兩個union中分別有所登記,。因此,我們必須將xs_ext2的信息也添加到這兩個 union中: ---linux/include/linux/fs.h.orig +++linux/include/linux/fs.h *************** *** 481,485 **** struct minix_inode_info minix_i; struct ext2_inode_info ext2_i; + struct xs_ext2_inode_info xs_ext2_i; struct ext3_inode_info ext3_i; *************** *** 727,731 **** struct minix_sb_info minix_sb; struct ext2_sb_info ext2_sb; + struct xs_ext2_sb_info xs_ext2_sb; struct ext3_sb_info ext3_sb; 好了,,源代碼的修改工作到此結束,。接下來就是第三步工作——編譯源代碼。首先我們要把我們的xs_ext2加到編譯選項中去,,以便在做make menuconfig的時候,,可以將該選項加上去。做這項工作需要修改三個文件: ---linux/Documentation/Configure.help.orig +++linux/Documentation/Configure.help …… *************** *** 14016,14023 **** be compiled as a module, and so this could be dangerous. Most everyone wants to say Y here. +My Second extended fs support +CONFIG_XS_EXT2_FS + This is the test of adding a self-defined filesystem. Ext3 journalling file system support (EXPERIMENTAL) 在上面這段程序中添加了關于xs_ext2的幫助,,也就是在做make menuconfig的時候可以查看該選項的有關幫助的內(nèi)容,。 ---linux/fs/Config.in.orig +++linux/fs/Config.in *************** *** 79,84 **** tristate 'Second extended fs support' CONFIG_EXT2_FS +tristate 'My Second extended fs support' CONFIG_XS_EXT2_FS + tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS] 在上面這段程序中添加關于xs_ext2配置宏,將編譯選項和宏關聯(lián)起來,。 ---linux/fs/Makefile.orig +++linux/fs/Makefile *************** *** 30,32 **** subdir-$(CONFIG_EXT2_FS) += ext2 +subdir-$(CONFIG_XS_EXT2_FS) += xs_ext2 subdir-$(CONFIG_ZLIB_FS_INFLATE) += inflate_fs 在上面這段程序中,,添加了xs_ext2目錄,將宏與源代碼目錄關聯(lián)起來,。 完成這些之后,,我們已經(jīng)成功地將我們的源代碼與編譯選項關聯(lián)。但是不要忘了,,我們還有fs/xs_ext2目錄下的Makefile: ---linux/fs/xs_ext2/Makefile.orig +++linux/fs/xs_ext2/Makefile *************** *** 10,10 **** -O_TARGET := ext2.o +O_TARGET := xs_ext2.o 上面Makefile的修改是為了防止在連接的時候,,xs_ext2的目標文件與ext2的目標文件沖突。 一切都準備就緒了,,只等編譯連接生成內(nèi)核文件: #make menuconfig # 配置xs_ext2 #make dep #make clean #make bzImage 編譯一切OK,,只是在連接的時候出現(xiàn)了以下錯誤: fs/fs.o: In function `xs_ext2_free_blocks': fs/fs.o(.text+0x263a5): undefined reference to `xs_ext2_clear_bit' fs/fs.o: In function `xs_ext2_new_block': fs/fs.o(.text+0x26674): undefined reference to `xs_ext2_test_bit' fs/fs.o(.text+0x26697): undefined reference to `xs_ext2_find_next_zero_bit' fs/fs.o(.text+0x26701): undefined reference to `xs_ext2_find_next_zero_bit' fs/fs.o(.text+0x26847): undefined reference to `xs_ext2_find_first_zero_bit' fs/fs.o(.text+0x26899): undefined reference to `xs_ext2_test_bit' fs/fs.o(.text+0x26932): undefined reference to `xs_ext2_set_bit' fs/fs.o(.text+0x26a3a): undefined reference to `xs_ext2_set_bit' fs/fs.o: In function `xs_ext2_free_inode': fs/fs.o(.text+0x27ca2): undefined reference to `xs_ext2_clear_bit' fs/fs.o: In function `xs_ext2_new_inode': fs/fs.o(.text+0x27f8a): undefined reference to `xs_ext2_find_first_zero_bit' fs/fs.o(.text+0x27fa8): undefined reference to `xs_ext2_set_bit' make: *** [vmlinux] Error 1 只要編譯不出現(xiàn)問題,連接錯誤還是比較好辦的,。從顯示出來的錯誤分析,,估計是缺了這些函數(shù)的定義。根據(jù)逆向思維方法,,只要在Linux源代碼中搜索 ext2_clear_bit,,ext2_test_bit等函數(shù),找到它們之后,,同樣復制一份,,改成 xs_ext2_cear_bit,xs_ext2_test_bit等函數(shù)名就可以了,。我們對這些函數(shù)逐個擊破,,先來搜索 ext2_clear_bit,。在include/asm/bitops.h中可以發(fā)現(xiàn)這些函數(shù)群。OK,,無需客氣,,三下五除二,全部把它們復制一份再修 改掉,,我們已經(jīng)看到勝利的曙光就在眼前了,! ---linux/include/asm/bitops.h.orig +++linux/include/asm/bitops.h *************** *** 369,379**** #define ext2_set_bit __test_and_set_bit #define ext2_clear_bit __test_and_clear_bit #define ext2_test_bit test_bit #define ext2_find_first_zero_bit find_first_zero_bit #define ext2_find_next_zero_bit find_next_zero_bit +#define xs_ext2_set_bit __test_and_set_bit +#define xs_ext2_clear_bit __test_and_clear_bit +#define xs_ext2_test_bit test_bit +#define xs_ext2_find_first_zero_bit find_first_zero_bit +#define xs_ext2_find_next_zero_bit find_next_zero_bit 添加完了以后,,保存,,退出?;氐絣inux目錄下,,再次做make bzImage(這次不用做make clean和make dep了)。 一切OK,!恭喜你,你的第一部分工作——克隆ext2文件系統(tǒng)已經(jīng)完成了,。再回過來想一下,,linux/include/asm/bitops.h 中這些宏是干什么用的。顯然,,ext2需要的這些操作是和計算機的CPU指令相關的,。因此,要把這些指令單獨拎出來,,放到linux/include /asm下,,因為asm這個目錄是一個連接,不同的計算機類型是不同的,,在Intel x86的機器上一般是連接到linux/include/asm-i386下,。 我們添加的xs_ext2文件系統(tǒng)是否可以正常使用呢?下面我們來對添加的xs_ext2文件系統(tǒng)進行一下測試: #dd if=/dev/zero of=myfs bs=1M count=1 #mkfs.ext2 myfs #mount –t xs_ext2 –o loop ./myfs /mnt #mount /dev/hda3 on / type ext2 (rw) none on /proc type proc (rw) /root/myfile on /mnt xs_ext2 (rw,loop=/dev/loop0) #umount /mnt #mount –t ext2 –o loop ./myfs /mnt #mount /dev/hda3 on / type ext2 (rw) none on /proc type proc (rw) /root/myfile on /mnt ext2 (rw,loop=/dev/loop0) # 對上面的命令我們逐一解釋: 第一條dd if=/dev/zero of=myfs bs=1M count=1: 創(chuàng)建大小為1M的,,名字為myfs的,,內(nèi)容全為0的文件。 第二條mkfs.ext2 myfs: 將myfs格式化成ext2文件系統(tǒng),。從理論上來看,,xs_ext2和ext2是完全一致的,當然除了名字外,,所以,,下面我們可以試著用xs_ext2文件系統(tǒng)格式去mount我們剛剛做出來的ext2文件系統(tǒng)。 第三條mount –t xs_ext2 –o loop ./myfs /mnt: 將myfs通過loop設備mount到/mnt目錄下,。請注意,,我們用的參數(shù)是-t xs_ext2,,也就是用xs_ext2文件系統(tǒng)格式去mount的,發(fā)現(xiàn)這樣mount是可以的,,也就證明了新內(nèi)核已經(jīng)支持我們的新文件系統(tǒng)xs_ext2,。 第四條mount: 用來檢查當前的系統(tǒng)的mount情況。注意最后一行,,發(fā)現(xiàn)我們的xs_ext2已經(jīng)被內(nèi)核所認可,,證明我們前面的實驗是完全成功的! 第五條 umount /mnt: 將原來的mount的文件系統(tǒng)umount下來,,準備下一步測試,。 第六條mount –t ext2 –o loop ./myfs /mnt: 將myfs通過loop設備mount到/mnt目錄下。這次我們用的參數(shù)是-t ext2,,這樣做的目的是再來檢查一下xs_ext2和ext2是否完全一致,,發(fā)現(xiàn)這樣mount是可以的。也證明了ext2和xs_ext2是一致的,。 第七條mount: 檢查結果證明我們的推測是完全正確的,。 錯誤處理: 1. 當執(zhí)行mount –t xs_ext2 –o loop ./myfs /mnt 時候,出現(xiàn) all of your loopback devices are in use時候,。解決方法如下: 以root 用戶進入/usr/src/linux/目錄下 2.當執(zhí)行mount –t xs_ext2 –o loop ./myfs /mnt 時候,出現(xiàn) xs_ext2 is not supported by kernel時候,。解決方法如下: 需要把內(nèi)核重新編譯下 #Make menuconfig #Make dep #Make clean #Made bzImage #make modules #cp /usr/src/linux/System.map /boot/System.map-2.4.18 #cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-2.4.18 #cd /boot #rm -f System.map vmlinuz #ln -s vmlinuz-2.4.18 vmlinuz #ln -s System.map-2.4.18 System.map #shutdown -r now 重新進入/root #dd if=/dev/zero of=myfs bs=1M count=1 #mkfs.ext2 myfs #mount –t xs_ext2 –o loop ./myfs /mnt #mount /dev/hda3 on / type ext2 (rw) none on /proc type proc (rw) /root/myfile on /mnt xs_ext2 (rw,loop=/dev/loop0) #umount /mnt #mount –t ext2 –o loop ./myfs /mnt #mount /dev/hda3 on / type ext2 (rw) none on /proc type proc (rw) /root/myfile on /mnt ext2 (rw,loop=/dev/loop0) |
|