Linux內(nèi)核中的GCC特性了解用于C語言的GCC擴(kuò)展_第1頁
Linux內(nèi)核中的GCC特性了解用于C語言的GCC擴(kuò)展_第2頁
Linux內(nèi)核中的GCC特性了解用于C語言的GCC擴(kuò)展_第3頁
Linux內(nèi)核中的GCC特性了解用于C語言的GCC擴(kuò)展_第4頁
Linux內(nèi)核中的GCC特性了解用于C語言的GCC擴(kuò)展_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、新的體系結(jié)構(gòu)上運行。Linux還利用GCC中的特性(稱為擴(kuò)展)實現(xiàn)更多功能和優(yōu)化。本文討論一些重要的擴(kuò)展,講解如何在Linux內(nèi)核中使用它們。GCC當(dāng)前的穩(wěn)定版本(版本4.3.2)支持C標(biāo)準(zhǔn)的三個版本:InternationalOrganizationforStandardization(ISO)最初的C語言標(biāo)準(zhǔn)(ISOC89或C90)帶修正1的ISOC90當(dāng)前的ISOC99(這是GCC使用的默認(rèn)標(biāo)準(zhǔn),本文也假設(shè)采用這種標(biāo)準(zhǔn))注意:本文假設(shè)使用ISOC99標(biāo)準(zhǔn)。如果指定比ISOC99版本舊的標(biāo)準(zhǔn),那么可能無法使用本文描述的一些擴(kuò)展??梢栽诿钚猩鲜褂?std選項指定GCC使用的實際標(biāo)準(zhǔn)。可以通

2、過GCC手冊查看哪個標(biāo)準(zhǔn)版本支持哪些擴(kuò)展??梢砸詭追N方式對可用的C擴(kuò)展進(jìn)行分類。本文把它們分為兩大類:功能性擴(kuò)展提供新功能。優(yōu)化擴(kuò)展幫助生成更高效的代碼。功能性擴(kuò)展先討論一些擴(kuò)展標(biāo)準(zhǔn)C語言的GCC擴(kuò)展。類型發(fā)現(xiàn)GCC允許通過變量的引用識別類型。這種操作支持泛型編程。在C+、Ada和Java語言等許多現(xiàn)代編程語言中都可以找到相似的功能。Linux使用typeof構(gòu)建min和max等依賴于類型的操作。清單1演示如何使用typeof構(gòu)建一個泛型宏(見./linux/include/linux/kernel.h)。清單1.使用typeof構(gòu)建一個泛型宏還可以使用范圍進(jìn)行初始化,如下所示(見./linu

3、x/arch/cris/arch-v32/kernel/smp.c)。在#definemin(x,y)(typeof(x)_min1=(x);typeof(y)_min2=(y);(void)(&_min1=&_min2);_min1_min2?_min1:_min2;)范圍擴(kuò)展GCC支持范圍,在C語言的許多方面都可以使用范圍。其中之一是switch/case塊中的case語句。在復(fù)雜的條件結(jié)構(gòu)中,通常依靠嵌套的if語句實現(xiàn)與清單2(見./Linux/drivers/scsi/sd.c)相同的結(jié)果,但是清單2更簡潔。使用switch/case也可以通過使用跳轉(zhuǎn)表實現(xiàn)進(jìn)行編譯器優(yōu)化。清單2.在c

4、ase語句中使用范圍staticintsd_major(intmajor_idx)switch(major_idx)case0:returnSCSI_DISK0_MAJOR;case1.7:returnSCSI_DISK1_MAJOR+major_idx-1;case8.15:returnSCSI_DISK8_MAJOR+major_idx-8;default:BUG;return0;/*shutupgcc*/這個示例中,spinlock_t創(chuàng)建一個大小為LOCK_COUNT的數(shù)組。數(shù)組的每個元素初始化為SPIN_LOCK_UNLOCKED值。/*Vectoroflocksusedforvar

5、iousatomicoperations*/spinlock_tcris_atomic_locks=0.LOCK_COUNT-1=SPIN_LOCK_UNLOCKED;范圍還支持更復(fù)雜的初始化。例如,以下代碼指定數(shù)組中幾個子范圍的初始值。intwidths=0.9=1,10.99=2,100=3;零長度的數(shù)組在C標(biāo)準(zhǔn)中,必須定義至少一個數(shù)組元素。這個需求往往會使代碼設(shè)計復(fù)雜化。但是,GCC支持零長度數(shù)組的概念,這對于結(jié)構(gòu)定義尤其有用。這個概念與ISOC99中靈活的數(shù)組成員相似,但是使用不同的語法。下面的示例在結(jié)構(gòu)的末尾聲明一個沒有成員的數(shù)組(見./Linux/drivers/IEeel394/

6、rawl394-private.h)。這允許結(jié)構(gòu)中的元素引用結(jié)構(gòu)實例后面緊接著的內(nèi)存。在需要數(shù)量可變的數(shù)組成員時,這個特性很有用。structiso_block_storeatomic_trefcount;size_tdata_size;quadlet_tdata0;判斷調(diào)用地址在許多情況下,需要判斷給定函數(shù)的調(diào)用者。GCC提供用于此用途的內(nèi)置函數(shù)還可以使用范圍進(jìn)行初始化,如下所示(見./linux/arch/cris/arch-v32/kernel/smp.c)。在還可以使用范圍進(jìn)行初始化,如下所示(見./linux/arch/cris/arch-v32/kernel/smp.c)。在_bu

7、iltin_return_address。這個函數(shù)通常用于調(diào)試,但是它在內(nèi)核中還有許多其他用途。如下面的代碼所示,_builtin_return_address接收一個稱為level的參數(shù)。這個參數(shù)定義希望獲取返回地址的調(diào)用堆棧級別。例如,如果指定level為0,那么就是請求當(dāng)前函數(shù)的返回地址。如果指定level為1,那么就是請求進(jìn)行調(diào)用的函數(shù)的返回地址,依此類推。void*_builtin_return_address(unsignedintlevel);在下面的示例中(見./linux/kernel/softirq.c),local_bh_disable函數(shù)在本地處理器上禁用軟中斷,從而禁

8、止在當(dāng)前處理器上運行softirqs、tasklets和bottomhalves。使用_builtin_return_address捕捉返回地址,以便在以后進(jìn)行跟蹤時使用這個地址。voidlocal_bh_disable(void)_local_bh_disable(unsignedlong)_builtin_return_address(0);在編譯時,可以使用常量檢測GCC提供的一個內(nèi)置函數(shù)判斷一個值是否是常量。這種信息非constantfolding)優(yōu)化的表達(dá)式。常有價值,因為可以構(gòu)造出能夠通過常量疊算(_builtin_constant_p函數(shù)用來檢測常量。_builtin_cons

9、tant_p的原型如下所示。注意,因為GCC不容易證明某些值是否是常量。builtin_constant_p并不能檢測出所有常量,int_builtin_constant_p(exp)Linux相當(dāng)頻繁地使用常量檢測。在清單(見./linux/include/linux/log2.h),使用常量檢測優(yōu)化表達(dá)式是常量,那么就使用可以優(yōu)化的常量表達(dá)式。函數(shù)把值向上取整到2的冪。3所示的示例中roundup_pow_of_two宏。如果發(fā)現(xiàn)如果表達(dá)式不是常量,就調(diào)用另一個宏清單3.使用常量檢測優(yōu)化宏函數(shù)#defineroundup_pow_of_two(n)(_builtin_constant_p(

10、n)?(n=1)?1:(1ULlen,skb-csum);if(likely(!sum)if(unlikely(skb-ip_summed=CHECKSUM_HW)netdev_rx_csum_fault(skb-dev);skb-ip_summed=CHECKSUM_UNNECESSARY;returnsum;預(yù)抓取另一種重要的性能改進(jìn)方法是把必需的數(shù)據(jù)緩存在接近處理器的地方。問數(shù)據(jù)花費的時間。大多數(shù)現(xiàn)代處理器都有三類內(nèi)存:緩存可以顯著減少訪一級緩存通常支持單周期訪問二級緩存支持兩周期訪問系統(tǒng)內(nèi)存支持更長的訪問時間為了盡可能減少訪問延時并由此提高性能,最好把數(shù)據(jù)放在最近的內(nèi)存中。手工執(zhí)行這個

11、任務(wù)稱為預(yù)抓取。GCC通過內(nèi)置函數(shù)builtin_prefetch支持?jǐn)?shù)據(jù)的手工預(yù)抓取。在需要數(shù)據(jù)之前,使用這個函數(shù)把數(shù)據(jù)放到緩存中。如下所示,builtin_prefetch函數(shù)接收三個參數(shù):數(shù)據(jù)的地址rw參數(shù),使用它指明預(yù)抓取數(shù)據(jù)是為了執(zhí)行讀操作,還是執(zhí)行寫操作locality參數(shù),使用它指定在使用數(shù)據(jù)之后數(shù)據(jù)應(yīng)該留在緩存中,還是應(yīng)該清除void_builtin_prefetch(constvoid*addr,intrw,intlocality);6是一個輔助函數(shù)示例,它使用內(nèi)置函數(shù)的包裝器(見Linux內(nèi)核經(jīng)常使用預(yù)抓取。通常是通過宏和包裝器函數(shù)使用預(yù)抓取。清單./linux/inclu

12、de/linux/prefetch.h)。這個函數(shù)為流操作實現(xiàn)預(yù)抓取機制。使用這個函數(shù)通??梢詼p少緩存缺失和停頓,從而提高性能。清單6.范圍預(yù)抓取的包裝器函數(shù)#ifndefARCH_HAS_PREFETCH#defineprefetch(x)_builtin_prefetch(x)#endifstaticinlinevoidprefetch_range(void*addr,size_tlen)#ifdefARCH_HAS_PREFETCHchar*cp;char*end=addr+len;for(cp=addr;cpend;cp+=PREFETCH_STRIDE)prefetch(cp);#e

13、ndif變量屬性除了本文前面討論的函數(shù)屬性之外,GCC還為變量和類型定義提供了屬性。最重要的屬性之一是aligned屬性,它用于在內(nèi)存中實現(xiàn)對象對齊。除了對于性能很重要之外,某些設(shè)備或硬件配置也需要對象對齊。aligned屬性有一個參數(shù),它指定所需的對齊類型。下面的示例用于軟件暫停(見./Linux/arch/i386/mm/init.c)。在需要頁面對齊時,定義PAGE_SIZE對象。char_nosavedataswsusp_pg_dirPAGE_SIZE_attribute_(aligned(PAGE_SIZE);清單7中的示例說明關(guān)于優(yōu)化的兩點:packed屬性打包一個結(jié)構(gòu)的元素,從而盡可能減少它們占用的空間。這意味著,如果8位)。位字段壓縮為一位,而不會定義一個char變量,它占用的空間不會超過一字節(jié)(占用更多存儲空間。這段源代碼使用一個attribute_聲明進(jìn)行優(yōu)化,它用逗號分隔的列表定義多個屬性。清單7.結(jié)構(gòu)打包和設(shè)置多個屬性staticstructswsusp_headercharreservedPAGE_SIZE-20-sizeof(swp_entry_t);swp_entry_timage;charori

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論