天天看點

uefi開發 c語言,Cstyle的C語言筆記 ---UEFI開發過程中須培養的N個習慣

有一句話說的很經典,好的程式不是給機器來讀的,能被機器讀懂的程式充其量算是正确的程式,而能被人讀懂的程式才算是好程式。那怎麼樣的程式才算是人能讀懂的程式呢,小弟不才雖沒寫過幾句代碼,但是還是想說說個人的看法。

個人認為寫好程式大概分為幾個步驟:

1.寫正确的程式,如果一個程式邏輯不對不能實作該有的功能,那麼哪怕你寫的再漂亮,用了再多的進階的程式設計技巧和算法,那也絕得不算是一個好的程式,隻能算是一個失敗的程式。

2.寫自己看得懂的程式。或許有人會說我寫的程式很好,很巧妙,用到了某種語言當中的非常巧妙的技巧,執行效率很高,占用資源很少,但是代碼隻有他一個人能看懂。或許如果過了一段時間之後它自己 再看當初自己寫的代碼也看不懂了。這種程式我們認為它不算是好程式。

3.寫别人看得懂的程式。如果你寫的程式給你的隊友來讀,他不不懂的話,那麼你寫的程式就不能算是好程式,真正的好的程式是随便把程式給誰來讀,他們都能很快的并且準确的讀懂你想寫什麼,就像是讀一本小說,别人能夠陶醉其中,而不是各種抱怨,各種讀不懂,各種挑刺。

那麼怎麼才能寫好的程式呢?小弟随沒寫很多的代碼,但是還算是讀過不少,下面來給自己做一個總結,就以UEFI的代碼作為執行個體:

一.合理的安排架構你的源碼,把相關性最強的部分組合在一起,盡量做到子產品内的内聚性,減少子產品間的耦合性。

把功能相關的内容放在一起,比如你有一個OEM相關的功能,需要在SEC,PEI,dxe三個階段都需要做一些特别的事情,那麼你就可以建立一個子產品,可以命名為OEMModule,它包含以下幾個檔案:OemSec.asm,OemPei.c,OemDxe.c,

Oemmake.mak,OemXxx.xxx等,在每一個檔案裡面實作相應階段但功能類似的功能。

二.合理的利用開發語言中的一些封裝的工具。

UEFI主要是用C語言開發的,那麼我們就可以使用C語言當中的一些好的功能,列舉如下:

1.在頭檔案裡面使用#ifndef #endif來保證頭檔案隻會被編譯一次,加快編譯速度和減少子產品間的幹擾。

2.使用#define來定義一些常量,比如數組長度,TURE FAILSE

3.使用#typedef來給我們自定義的變量重新取别名。如:

#typedef UINT64    EFI_PHYSICAL_ADDRESS;

#define EFI_SUCCESS  RETURN_SUCCESS

4.使用#define來定義宏,把一些常見的語句封裝成代碼塊,雖然這樣會增加總代碼量,但是可以使代碼讀起來更簡潔。如:

#define EFI_SIZE_TO_PAGES(Size)  (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0))

5.使用#if等宏編譯指令來控制編譯順序,友善對項目進行配置。類似于支援的處理器架構,是否打開編譯優化選項,是否打開調試模式等,讓同一個方法能支援多種功能。如:

#if   defined (MDE_CPU_IA32)  #if defined DEBUG

6.合理的使用ASSERT()printf()CR()等工具,當出現issue的時候可以通過相應的工具把異常抛出來,友善調試。

7.合理的利用C語言中的結構體,共同體,位域,指針等來構造複雜的資料結構,并用其來服務我們要實作的功能。

8.合理的資料封裝與隐藏:類似該函數裡面的IN關鍵詞标示出了,該函數的參數是輸入的,EFI_HANDLEs是一個自定義變量,它展示給調用者是一個簡單的Void *類型,隻在其核心部分使用其真正的類型,通過Void *這個萬能的指指針,很好的實作了資料的封裝和實作的隐藏:CoreValidateHandle (

IN

EFI_HANDLE

UserHandle )

三.選擇并形成一套自己的程式設計習慣,如命名規則等

選擇自己的變量函數命名規則,并長期堅持形成習慣。如:UEFI當中常用的幾種習慣:

1.全局變量:LIST_ENTRY    gHandleList

2.結構内部變量:

LIST_ENTRY      mProtocolDatabase

3.類似駝峰命名法和匈牙利命名法的合體的命名規則:

EFI_LOCK        gProtocolDatabaseLock

四.要寫好的注釋,而不僅僅是寫注釋。

寫好注釋,而不是寫注釋,寫錯誤的注釋往往比沒寫注釋更可怕。

PROTOCOL_INTERFACE  *

CoreGetProtocolInterface (

IN  EFI_HANDLE                UserHandle,

IN  EFI_GUID                  *Protocol

)

{

EFI_STATUS          Status;

PROTOCOL_ENTRY      *ProtEntry;

PROTOCOL_INTERFACE  *Prot;

IHANDLE             *Handle;

LIST_ENTRY          *Link;

Status = CoreValidateHandle (UserHandle);

if (EFI_ERROR (Status)) {

return NULL;

}

Handle = (IHANDLE *)UserHandle;

//

// Look at each protocol interface for a match

//

for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {

Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);

ProtEntry = Prot->Protocol;

if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {

return Prot;

}

}

return NULL;

}

五.先到這裡,下次再總結。

轉載請注明出處

[email protected]  //  http://blog.csdn.net/CStyle_0x007