低固存嵌入式系統(tǒng)的uClinux小型化方法
系統(tǒng)調(diào)用約有177個,包括關于進程的調(diào)用函數(shù)、文件的調(diào)用函數(shù),以及其它相關的調(diào)用,其中文件系統(tǒng)的調(diào)用占了71個。由于沒有根系統(tǒng),系統(tǒng)調(diào)用中涉及到從根文件系統(tǒng)上或掛接在它某個文件節(jié)點上的其它文件系統(tǒng)上,裝載、執(zhí)行可執(zhí)行文件的系統(tǒng)調(diào)用都是沒必要的,所以必須做相應的更改。典型的是系統(tǒng)調(diào)用execve(),其執(zhí)行流程主干線如圖2所示。
exeeve()
↓
do_exeeve()
↓
open_execve()
↓
prepare_binpma()
↓
search_binary_hanlder()
圖2 execve()執(zhí)行流程
do_execve()是execve()的核心,它調(diào)用open_exec()尋找可執(zhí)行文件并打開,函數(shù)open_exec()返回一個file結構指針,代表著讀入可執(zhí)行文件的上下文,將其保存在數(shù)據(jù)結構bprm中。然后調(diào)用prepare_binprm()完成對bprm的進一步工作,包括從可執(zhí)行文件頭讀取相關信息,以及拷貝運行環(huán)境參數(shù)等到bprm 中。內(nèi)核中有一個叫formats的隊列,隊列中的每個成員只認識并且處理一種特定格式的可執(zhí)行文件的運行。search_binary_handler()就是在formats的隊列中,尋找跟bprm中信息相符的一個成員,并由此成員來完成可執(zhí)行文件的裝載并初始化運行。由于不存在從文件系統(tǒng)加載可執(zhí)行文件,所以bpma數(shù)據(jù)結構,及涉及prepare_binprm(),search_binary_hanlder()等相關操作都是可以刪除的。
再者,由于沒有可供mount的文件節(jié)點,所以有關掛接的系統(tǒng)調(diào)用也必須做出調(diào)整。比如:mount()是用于文件系統(tǒng)掛接的系統(tǒng)調(diào)用,完全可以刪去;內(nèi)核函數(shù)mount_root()在初始化時用于安裝根文件系統(tǒng),也是可以刪去的;vfsmount()是內(nèi)核數(shù)據(jù)結構,用于描述掛載節(jié)點的信息,包括掛載點的根目錄,被掛載系統(tǒng)的級塊指針等信息。vfsmount()完全是跟掛載有關的,可以將它刪除,同時內(nèi)核中有好多涉及操作此數(shù)據(jù)結構的函數(shù)也必須做出更改。比如alloc_vfsmnt()和free_vfsmnt()是分配和釋放vfsmount結構,完全可以刪去,但有些內(nèi)核函數(shù)只有一部分涉及到對vfsrmnt結構的操作,所以不能全部刪除,必須對相應部分做出修改。
1.2.2 對內(nèi)核啟動初始化的影響
由于init()進程不能從根文件系統(tǒng)加載,所以凡是涉及根文件系統(tǒng)初始化函數(shù)的都必須刪除,以支持內(nèi)核與應用程序一體化。初始化進程init代碼如下:
static int init(void *unused)
{……
if(open(/dev/console,O_RDWR,0) 0)
……
if(execute_command)
execve(execute_command,argv_init,envp_init);
execve(/sbin/init,argv_init;envp_init);
……
panic(No init found.Try passing init= option to kernel);
}
init()完成系統(tǒng)的初始化,包括外部設備的初始化,釋放init()前初始化后代碼占用的內(nèi)存,以及控制臺的初始化,最后從根文件系統(tǒng)加載整個系統(tǒng)的第一個進程init,它是所有進程的“鼻祖”。由于根文件的刪除,所以可以刪除控制臺以及調(diào)用init進程。
1.2.3 對ReFS和外部設備的影響
ReFS可以像mount_root()那樣直接把ReFS當成根文件系統(tǒng)來裝,但它并不像根文件系統(tǒng)那樣有bash,gretty等應用程序,也不具備掛載其它系統(tǒng)的能力,所以不是真正的根文件系統(tǒng)。內(nèi)核中有幾個根文件系統(tǒng)和外設相關的重要內(nèi)核級全局變量:file_system_type,btkdevs[MAX_BLKDEV],chrdevs[MAX_CHRDEV],super_block。
file_system_type是一個描述系統(tǒng)中所有支持的文件系統(tǒng)的數(shù)據(jù)結構。VFS在內(nèi)存中維護這樣一個數(shù)據(jù)結構的列表,全局指針變量為file_systems。新文件系統(tǒng)必須通過register_filesystem()來注冊以讓系統(tǒng)識別,即是在鏈表file_systems結尾插人一個file_systm_type數(shù)據(jù)結構。blkdevs[MAX_BLKDEV]和chrdevs[MAX_CHRDEV]分別為塊設備和字符設備的注冊數(shù)組,包含主設備號和次設備號,以及有關設備操作的跳轉指針。塊設備和字符設備分別通過register_blkdev()和register_chrdev()向系統(tǒng)注冊設備。super_block是超級塊數(shù)據(jù)結構,存放著整個文件系統(tǒng)的信息和超級塊操作的函數(shù)。在通用內(nèi)核中根文件系統(tǒng)的安裝的順序是:從file_systems處取得根文件系統(tǒng)的read_super(),read_super()指向具體的驅(qū)動程序讀操作,通過讀取得超級塊,然后在內(nèi)存中創(chuàng)建inode,file,dentry等數(shù)據(jù)結構,用于文件的讀寫操作。
在這里,同樣可以用與根文件系統(tǒng)相同的裝載方法來初始化ReFS,但是比前者簡單多,因為后者不涉及安裝掛載點及與此相關的操作。對于外設,內(nèi)核一般是通過根文件系統(tǒng)搜索到設備文件,再來訪問外設,當中要涉及到搜索路徑和掛接點到外設翻譯的問題,而在這里外設是獨立的,不依賴于根系統(tǒng),所以實現(xiàn)起來更簡單,可以直接依據(jù)內(nèi)核數(shù)據(jù)結構blkdevs[]和chrdevs[]提供的操作函數(shù)表指針,來操作具體的驅(qū)動程序操作外設。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關文章:linux教程
評論