核心組件用__setup宏來註冊關鍵字及相關聯的處理函數,__setup宏在include/linux/init.h中定義,其原型如下:
__setup(string, function_handler)
其中:string是關鍵字,function_handler是關聯處理函數。__setup只是告訴核心在啟動時輸入串中含有string時,核心要去執行function_handler。String必須以“=”符結束以使parse_args更方便解析。緊隨“=”後的任何文本都會作為輸入傳給 function_handler。
下面的例子來自於net/core/dev.c,其中netdev_boot_setup作為處理常式被註冊給“netdev=”關鍵字:
__setup("netdev=", netdev_boot_setup);
不 同的關鍵字可以註冊相同的處理函數,例如在net/ethernet/eth.c中為“ether =”關鍵字註冊了同樣的處理函數 netdev_boot_setup。當代碼作為模組被編譯時間,__setup宏被忽視,你可以在include/linux/init.h中看到 __setup宏是怎樣變化的,不管後續包含它的檔案是否是模組,include/linux/init.h都是獨立的。
start_kernel兩次調用parse_args解析啟動配置字串的原因是啟動選項事實上分為兩類,且每次調用值能夠兼顧到其中一類:
預設選項:
絕大多數選項歸於此類,這些選項由__setup宏定義並在第二次調用parse_args時處理。
先期(處理)選項:
在 核心啟動階段,有些選項要在其它選項之前被處理,核心提供了early_param宏以代替__setup宏申明此類選項。這些選項由 parse_early_params函數解析。early_param宏和__setup宏僅有的不同就是前者設定了一個特殊標誌讓核心能夠區分兩種不同的狀況。這個標誌是我們將在“.init.setup記憶體區”小節中看到的obs_kernel_param結構的一部分。
啟動時選項在核心 2.6中的處理方式已經改變,但並非所有的核心代碼都因此而更新。在最近一次改變之前,還僅用__setup宏。因此,遺留下來將被更新的代碼現在使用 __obsolete_setup宏。但使用者用__obsolete_setup宏定義的選項給核心時,核心列印一條警告訊息說明它已是廢棄狀態,並提供一個檔案指標和隨後被公告的原始碼行資訊。
圖7-1概述了幾個宏之間的關係:它們都包裹了普通的__setup_param函數。
注意:傳給__setup宏的程式被放到.init.setup記憶體節,這樣,在“啟動時初始化代碼”一節中可以很清晰的看出這樣做的效果。