核心命令列處理

2021-07-07 04:52:01 字數 2878 閱讀 3571

**清單5-5是語法乏味的定義。回想**清單5-4,我們最初所呼叫的__setup巨集的形式如下:

__setup("console=", console_setup); 

經過稍稍簡化,編譯器在巨集擴充套件後,其預處理器產生如下結果:

static char __setup_str_console_setup __initdata = "console=";  

static struct obs_kernel_param __setup_console_setup  \  

__attribute__((__section__(".init.setup")))=  

;

為了增加可讀性,將上述結果的第2行和第3行採用unix的行續符"\"分隔開來。

我們故意略去了兩個和本次討論內容無關的編譯器屬性。簡要地說,__attribute_ used__(本身就是乙個隱藏了很多語法細節的巨集)會告訴編譯器發出乙個函式或變數,即使在編譯過程中並沒有用到任何優化引數 。__attribute__(aligned)會告訴編譯器按照特定的邊界來對齊結構,在本例中是sizeof(long)。

簡化處理後剩下的就是這種機制的核心部分。首先,編譯器會產生名為__setup_str_ console_setup的初始化後字元陣列,該陣列包含console=字串資訊;其次,編譯器會產生乙個包含三個成員的結構:指向核心命令列字串(在字元陣列中宣告)的指標、指向配置函式本身的指標和乙個簡單的標識。這裡的關鍵在於依附於結構的段屬性,該屬性會通知編譯器將該結構送到elf目標模組內名為.init.setup的特殊段中。在這個鏈結階段,所有由__setup巨集定義的結構一起被放置到這個.init.setup段中,實際結果就是建立了乙個包含這些結構的陣列。**清單5-6是.../init/main.c中的一部分內容,它們說明了這個資料是如何獲取和使用的。

**清單5-6 核心命令列處理

1 extern struct obs_kernel_param __setup_start, __setup_end;  

2  3 static int __init obsolete_checksetup(char *line)  

4  else if (!p->setup_func)  else if (p->setup_func(line + n))  

21                                  return 1;  

22                }  

23                p++;  

24        } while (p <

__setup_end);  

25        return 0;  

26 } 

對該段**解釋還算簡單。函式由乙個在main.c檔案中其他地方解析的單命令列引數呼叫。在這個例子中,我們要討論的指標line指向字串console=ttys0,115200,它是核心命令列的乙個組成部分。兩個外部結構指標__setup_start和__setup_end是在乙個鏈結指令碼文字檔案中定義的,而不是定義在c檔案或標頭檔案中。對於obs_kernel_param結構陣列用來標記該陣列起始和結束的標籤則存在於目標檔案的.init.setup段中。

在**清單5-6中,通過指標p對這個特殊的核心命令列引數尋找匹配資訊的過程,對整個結構都進行了掃瞄。具體在本例中,**要為字串資訊console=尋找匹配資訊,在這個相關的結構中,函式返回乙個指向console_setup()函式的指標,它會以該引數(字串ttys0,115200)作為其唯一的函式引數,這一處理過程會在核心命令列處理完畢之前不停地重複。

採用所描述的這種機制將目標物件存放到elf段的列表中,這種機制在核心中的許多地方都用到了。另乙個採用這種機制的例子是,使用__init巨集系列將初始化程式放到目標檔案中乙個普通的段中。與其很相近的__initdata被__setup巨集用來標記為只在初始化過程中用到的資料。使用這些巨集標記的初始化函式和資料被集中放到elf段中,接下來,當使用了這些用來初始化的函式和資料之後,核心會釋放之前它們所占用的記憶體空間。你也許在引導過程的最後階段看到過類似的核心資訊:"freeing init memory: 296k."。不同使用者對這些函式和資料的使用可能不盡相同,但是如果有三分之一兆,就值得使用__init巨集系列,這也恰恰就是使用前面宣告的__setup_str_console_setup陣列裡的__initdata巨集的目的所在。

你也許會對**清單5-6中的obsolete_符號感到迷惑,這是因為核心開發者正在用一種更通用的機制來代替核心命令列處理機制,以實現對引導時間和可載入模組引數的註冊。在當前情況下,__setup巨集宣告了幾百個引數,然而在新的開發中希望使用核心標頭檔案.../include/ linux/moduleparam.h中定義的一系列函式來實現,更值得注意的是使用module_param*巨集系列。這些內容將在第8章中介紹裝置驅動程式的時候詳細介紹。

上面所說的這種新機制通過在解析程式中包含乙個未知的函式指標引數進而保持了向後相容性,因此,對於module_param*結構來說,是未知的引數就會被視為未知引數,並且對命令列的處理過程就在開發者的控制下重新回到了原有的機制。在仔細研究../kernel/params.c中的**和.../init/main.c中的parse_args()呼叫後就可以對這一過程有很好的理解。

對於由__setup巨集所建立的結構obs_kernel_param,其中標誌(flag)成員的用途是最後要注意的內容。仔細研究**清單5-6就會明白。該結構中稱為early的標誌用來指示這個特定的核心命令列引數是否會在引導過程中預先使用,一些命令列引數就是特意要在引導過程中提前用到,那麼在這種情況下的標誌就會為提前解析命令列引數提供一種實現機制。你會在main.c**中看到乙個名為do_early_param()的函式,該函式會遍歷陣列,該陣列是__setup巨集結構由目標鏈結器產生的,同時該函式會處理每乙個被標記為預先使用的核心命令列引數,在引導過程執行這一處理操作時給開發者一些控制權。

命令列xml處理 命令列XML處理

命令列xml處理 就像我不願說的那樣,xml工具還沒有達到類似unix的命令列中可用的文字實用程式的便利程度。對於面向行的,空格或逗號分隔的文字檔案,使用sed,grep,xargs,wc,cut,pipe和短殼指令碼的巧妙組合可以完成的工作非常令人驚訝。我認為,xml並不是天生就可以抵抗平面文字檔...

命令列引數處理

url url include include include include include struct student optsting是選項引數組成的字串,字元後跟乙個冒號,表明該選項要求有引數。static const char optstring i n h?option結構稱為長選項表...

python命令列引數處理

本篇將介紹python中sys,getopt模組處理命令列引數 如果想對python指令碼傳引數,python中對應的argc,argv c語言的命令列引數 是什麼呢?需要模組 sys 引數個數 len sys.argv 指令碼名 sys.argv 0 引數1 sys.argv 1 引數2 sys....