引用自 http://www.blogbus.com/public/tb.php/4346144/15887442/5aaba108490b7c1550d529b8371fb1b4
創建和添加一個文件系統
一、問題描述
本項目的內容是要添加一個類似于ext2的自定義文件系統xs_ext2。我們對xs_ext2文件系統的描述如下:
1、xs_ext2文件系統的物理格式定義與ext2基本一致,除了xs_ext2的magic number是0x6666,而ext2的magic number是0xEF53。
2、xs_ext2是ext2的定制版本,它只支持原來ext2文件系統的部分操作,以及修改了部分操作。
文件系統的定義和操作是完成了,但不要忘了,這樣的一個文件系統如何去創建呢?我們最后還要提供一個創建xs_ext2文件系統的工具:mkfs.xs_ext2。
二、 解決方法
如何實現上面提出來的要求呢?首先從添加一個完全和ext2相同的xs_ext2開始,然后再對xs_ext2進行雕琢,逐步達到上一小節提到的要求:先修改magic number,再修改Linux對xs_ext2文件系統的一些操作。最后是創建文件系統的工具mkfs.xs_ext2的完成。
1. 添加一個和ext2完全相同的文件系統xs_ext2
要添加一個與ext2完全相同的文件系統xs_ext2,首先是確定實現ext2文件系統的內核源碼是由哪些文件組成。Linux源代碼結構很清楚地告訴我們:fs/ext2目錄下的所有文件是屬于ext2文件系統的。再檢查一下這些文件所包含的頭文件,可以初步總結出來Linux源代碼中屬于ext2文件系統的有:
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文件系統的源代碼到Linux源代碼。
由于本節工作是要克隆ext2文件系統到xs_ext2文件系統,所以我們需要把ext2部分的源代碼克隆到xs_ext2去,即復制一份以上所列的ext2源代碼文件給xs_ext2用。按照Linux源代碼的組織結構,我們把xs_ext2文件系統的源代碼存放到fs/xs_ext2下,頭文件放到include/linux下。在Linux的shell下,執行如下操作:
#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
這樣就完成了克隆文件系統工作的第一步——源代碼復制。對于克隆文件系統來說,這樣當然還遠遠不夠,因為文件里面的數據結構名、函數名、以及相關的一些宏等內容還沒有根據xs_ext2改掉,連編譯都通不過。
下面我們開始克隆文件系統的第二步:修改上面添加的文件的內容。為了簡單起見,我們做了一個最簡單的替換:將原來*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目錄下
文件內容如下:
#!/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
執行
%s/ext2/xs_ext2/gc
%s/EXT2/XS_EXT2/gc
以上文件修改完畢
關于具體文件系統部分的代碼是修改完了,但是關于具體文件系統和整個操作系統的接口部分是不是也需要修改呢?根據前面所學的內容,想起來我們還需要修改操作系統中所有文件系統都需要的兩個數據結構:struct super_block和struct inode。Linux要支持的文件系統,必須在這兩個結構中的兩個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的時候可以查看該選項的有關幫助的內容。
---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配置宏,將編譯選項和宏關聯起來。
---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目錄,將宏與源代碼目錄關聯起來。
完成這些之后,我們已經成功地將我們的源代碼與編譯選項關聯。但是不要忘了,我們還有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的目標文件沖突。
一切都準備就緒了,只等編譯連接生成內核文件:
#make menuconfig
#???? 配置xs_ext2
#make dep
#make clean
#make bzImage
編譯一切OK,只是在連接的時候出現了以下錯誤:
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
只要編譯不出現問題,連接錯誤還是比較好辦的。從顯示出來的錯誤分析,估計是缺了這些函數的定義。根據逆向思維方法,只要在Linux源代碼中搜索ext2_clear_bit,ext2_test_bit等函數,找到它們之后,同樣復制一份,改成xs_ext2_cear_bit,xs_ext2_test_bit等函數名就可以了。我們對這些函數逐個擊破,先來搜索ext2_clear_bit。在include/asm/bitops.h中可以發現這些函數群。OK,無需客氣,三下五除二,全部把它們復制一份再修改掉,我們已經看到勝利的曙光就在眼前了!
---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
添加完了以后,保存,退出。回到linux目錄下,再次做make bzImage(這次不用做make clean和make dep了)。
一切OK!恭喜你,你的第一部分工作——克隆ext2文件系統已經完成了。再回過來想一下,linux/include/asm/bitops.h中這些宏是干什么用的。顯然,ext2需要的這些操作是和計算機的CPU指令相關的。因此,要把這些指令單獨拎出來,放到linux/include/asm下,因為asm這個目錄是一個連接,不同的計算機類型是不同的,在Intel x86的機器上一般是連接到linux/include/asm-i386下。
我們添加的xs_ext2文件系統是否可以正常使用呢?下面我們來對添加的xs_ext2文件系統進行一下測試:
#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:
創建大小為1M的,名字為myfs的,內容全為0的文件。
第二條mkfs.ext2 myfs:
將myfs格式化成ext2文件系統。從理論上來看,xs_ext2和ext2是完全一致的,當然除了名字外,所以,下面我們可以試著用xs_ext2文件系統格式去mount我們剛剛做出來的ext2文件系統。
第三條mount –t xs_ext2 –o loop ./myfs /mnt:
將myfs通過loop設備mount到/mnt目錄下。請注意,我們用的參數是-t xs_ext2,也就是用xs_ext2文件系統格式去mount的,發現這樣mount是可以的,也就證明了新內核已經支持我們的新文件系統xs_ext2。
第四條mount:
用來檢查當前的系統的mount情況。注意最后一行,發現我們的xs_ext2已經被內核所認可,證明我們前面的實驗是完全成功的!
第五條 umount /mnt:
將原來的mount的文件系統umount下來,準備下一步測試。
第六條mount –t ext2 –o loop ./myfs /mnt:
將myfs通過loop設備mount到/mnt目錄下。這次我們用的參數是-t ext2,這樣做的目的是再來檢查一下xs_ext2和ext2是否完全一致,發現這樣mount是可以的。也證明了ext2和xs_ext2是一致的。
第七條mount:
檢查結果證明我們的推測是完全正確的。
錯誤處理:
1.?????? 當執行mount –t xs_ext2 –o loop ./myfs /mnt 時候,出現 all of your loopback devices are in use時候。解決方法如下:
以root 用戶進入/usr/src/linux/目錄下
??? # make menuconfig # 想必這一步大家只要試著編譯過內核的都會吧。
??? 將其它的選項默認,但是要留著
??? Loadable module support --->
??????? [*] Enable loadable module support
??????? [*] Set version information on all module symbols
??????? [*] Kernel module loader # 這個是必須的
??? Block devices --->
??????? < M > Loopback device support # 這個編譯為模塊,一會加載的時候要用到
??? 保存退出,剩下的就是一些常規步驟了:
??? # make dep
??? # make modules # 這個就不用解釋了吧
??? # mkdir /lib/modules/2.4.20-8/kernel/drivers/block # 沒有就建一個吧
??? # cp drivers/block/loop.o?? /lib/modules/2.4.20-8/kernel/drivers/block/loop.o
??? # insmod loop.o # 辛苦這么久就是為了這個了 :)
??? # lsmod # 查看一下吧 :)
2.當執行mount –t xs_ext2 –o loop ./myfs /mnt 時候,出現 xs_ext2 is not supported by kernel時候。解決方法如下:
需要把內核重新編譯下
#Make menuconfig
#Make dep
#Make clean
#Made bzImage
#make modules
#make modules_install
#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)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
