亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問板塊 發(fā)新帖
查看: 1070 | 回復(fù): 0
打印 上一主題 下一主題

linux內(nèi)核中用到的gcc擴(kuò)展 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2006-03-17 23:15 |只看該作者 |倒序?yàn)g覽
GNC CC是一個(gè)功能非常強(qiáng)大的跨平臺(tái)C編譯器,它對(duì)C 語(yǔ)言提供了很多擴(kuò)展,這些擴(kuò)展對(duì)優(yōu)化、目標(biāo)代碼布局、更安全的檢查等方面提供了很強(qiáng)的支持。本文把支持GNU 擴(kuò)展的C 語(yǔ)言稱為GNU C。
            
   Linux 內(nèi)核代碼使用了大量的 GNU C 擴(kuò)展,以至于能夠編譯 Linux 內(nèi)核的唯一編譯器是 GNU CC,以前甚至出現(xiàn)過(guò)編譯
Linux 內(nèi)核要使用特殊的 GNU CC 版本的情況。本文是對(duì) Linux 內(nèi)核使用的 GNU C
擴(kuò)展的一個(gè)匯總,希望當(dāng)你讀內(nèi)核源碼遇到不理解的語(yǔ)法和語(yǔ)義時(shí),能從本文找到一個(gè)初步的解答,更詳細(xì)的信息可以查看gcc.info。文中的例子取自
Linux 2.4.18。
  語(yǔ)句表達(dá)式
  GNU C 把包含在括號(hào)中的復(fù)合語(yǔ)句看做是一個(gè)表達(dá)式,稱為語(yǔ)句表達(dá)式,它可以出現(xiàn)在任何允許表達(dá)式的地方,你可以在語(yǔ)句表達(dá)式中使用循環(huán)、局部變量等,原本只能在復(fù)合語(yǔ)句中使用。例如:
++++ include/linux/kernel.h
159: #define min_t(type,x,y) \
160: ({ type __x = (x); type __y = (y); __x window_clamp, tcp_full_space(sk));
  復(fù)合語(yǔ)句的最后一個(gè)語(yǔ)句應(yīng)該是一個(gè)表達(dá)式,它的值將成為這個(gè)語(yǔ)句表達(dá)式的值。這里定義了一個(gè)安全的求最小值的宏,在標(biāo)準(zhǔn) C 中,通常定義為:
#define min(x,y) ((x) " "%s:%d", filename, line)
  使用 ## 的原因是處理 arg 不匹配任何參數(shù)的情況,這時(shí) arg 的值為空,GNUC 預(yù)處理器在這種特殊情況下,丟棄 ## 之前的逗號(hào),這樣
pr_debug("success!\n")
  擴(kuò)展為
printk("" "success!\n")
  注意最后沒有逗號(hào)。
  標(biāo)號(hào)元素
  標(biāo)準(zhǔn) C 要求數(shù)組或結(jié)構(gòu)變量的初使化值必須以固定的順序出現(xiàn),在 GNU C
中,通過(guò)指定索引或結(jié)構(gòu)域名,允許初始化值以任意順序出現(xiàn)。指定數(shù)組索引的方法是在初始化值前寫 '[INDEX] =',要指定一個(gè)范圍使用
'[FIRST ... LAST] =' 的形式,例如:
+++++ arch/i386/kernel/irq.c
1079: static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
  將數(shù)組的所有元素初使化為 ~0UL,這可以看做是一種簡(jiǎn)寫形式。要指定結(jié)構(gòu)元素,在元素值前寫 'FIELDNAME:',例如:
++++ fs/ext2/file.c
41: struct file_operations ext2_file_operations = {
42: llseek: generic_file_llseek,
43: read: generic_file_read,
44: write: generic_file_write,
45: ioctl: ext2_ioctl,
46: mmap: generic_file_mmap,
47: open: generic_file_open,
48: release: ext2_release_file,
49: fsync: ext2_sync_file,
50 };
  將結(jié)構(gòu) ext2_file_operations 的元素 llseek 初始化為 generic_file_llseek,元素 read
初始化genenric_file_read,依次類推。我覺得這是 GNU C
擴(kuò)展中最好的特性之一,當(dāng)結(jié)構(gòu)的定義變化以至元素的偏移改變時(shí),這種初始化方法仍然保證已知元素的正確性。對(duì)于未出現(xiàn)在初始化中的元素,其初值為 0。
  Case 范圍
  GNU C 允許在一個(gè) case 標(biāo)號(hào)中指定一個(gè)連續(xù)范圍的值,例如:
++++ arch/i386/kernel/irq.c
1062: case '0' ... '9': c -= '0'; break;
1063: case 'a' ... 'f': c -= 'a'-10; break;
1064: case 'A' ... 'F': c -= 'A'-10; break;
case '0' ... '9':
  相當(dāng)于
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
  聲明的特殊屬性
  GNU C 允許聲明函數(shù)、變量和類型的特殊屬性,以便手工的代碼優(yōu)化和更仔細(xì)的代碼檢查。要指定一個(gè)聲明的屬性,在聲明后寫
__attribute__ (( ATTRIBUTE ))
  其中 ATTRIBUTE 是屬性說(shuō)明,多個(gè)屬性以逗號(hào)分隔。GNU C 支持十幾個(gè)屬性,這里介紹最常用的:
   * noreturn
  屬性 noreturn 用于函數(shù),表示該函數(shù)從不返回。這可以讓編譯器生成稍微優(yōu)化的代碼,最重要的是可以消除不必要的警告信息比如未初使化的變量。例如:
++++ include/linux/kernel.h
47: # define ATTRIB_NORET __attribute__((noreturn)) ....
61: asmlinkage NORET_TYPE void do_exit(long error_code)
ATTRIB_NORET;
  * format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)
  屬性 format 用于函數(shù),表示該函數(shù)使用 printf, scanf 或 strftime 風(fēng)格的參數(shù),使用這類函數(shù)最容易犯的錯(cuò)誤是格式串與參數(shù)不匹配,指定 format 屬性可以讓編譯器根據(jù)格式串檢查參數(shù)類型。例如:
++++ include/linux/kernel.h?
89: asmlinkage int printk(const char * fmt, ...)
90: __attribute__ ((format (printf, 1, 2)));
  表示第一個(gè)參數(shù)是格式串,從第二個(gè)參數(shù)起根據(jù)格式串檢查參數(shù)。
  * unused
  屬性 unused 用于函數(shù)和變量,表示該函數(shù)或變量可能不使用,這個(gè)屬性可以避免編譯器產(chǎn)生警告信息。
  * section ("section-name")
  屬性 section 用于函數(shù)和變量,通常編譯器將函數(shù)放在 .text 節(jié),變量放在.data 或 .bss 節(jié),使用 section 屬性,可以讓編譯器將函數(shù)或變量放在指定的節(jié)中。例如:
++++ include/linux/init.h
78: #define __init __attribute__ ((__section__ (".text.init")))
79: #define __exit __attribute__ ((unused, __section__(".text.exit")))
80: #define __initdata __attribute__ ((__section__ (".data.init")))
81: #define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
82: #define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
83: #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
84: #define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
  連接器可以把相同節(jié)的代碼或數(shù)據(jù)安排在一起,Linux 內(nèi)核很喜歡使用這種技術(shù),例如系統(tǒng)的初始化代碼被安排在單獨(dú)的一個(gè)節(jié),在初始化結(jié)束后就可以釋放這部分內(nèi)存。
  * aligned (ALIGNMENT)
  屬性 aligned 用于變量、結(jié)構(gòu)或聯(lián)合類型,指定變量、結(jié)構(gòu)域、結(jié)構(gòu)或聯(lián)合的對(duì)齊量,以字節(jié)為單位,例如:
++++ include/asm-i386/processor.h
294: struct i387_fxsave_struct {
295: unsigned short cwd;
296: unsigned short swd;
297: unsigned short twd;
298: unsigned short fop;
299: long fip;
300: long fcs;
301: long foo;
......
308: } __attribute__ ((aligned (16)));
  表示該結(jié)構(gòu)類型的變量以 16 字節(jié)對(duì)齊。通常編譯器會(huì)選擇合適的對(duì)齊量,顯示指定對(duì)齊通常是由于體系限制、優(yōu)化等原因。
  * packed
  屬性 packed 用于變量和類型,用于變量或結(jié)構(gòu)域時(shí)表示使用最小可能的對(duì)齊,用于枚舉、結(jié)構(gòu)或聯(lián)合類型時(shí)表示該類型使用最小的內(nèi)存。例如:
++++ include/asm-i386/desc.h
51: struct Xgt_desc_struct {
52: unsigned short size;
53: unsigned long address __attribute__((packed));
54: };
  域 address 將緊接著 size 分配。屬性 packed 的用途大多是定義硬件相關(guān)的結(jié)構(gòu),使元素之間沒有因?qū)R而造成的空洞。
  當(dāng)前函數(shù)名
  GNU CC 預(yù)定義了兩個(gè)標(biāo)志符保存當(dāng)前函數(shù)的名字,__FUNCTION__ 保存函數(shù)在源碼中的名字__PRETTY_FUNCTION__
保存帶語(yǔ)言特色的名字。在 C 函數(shù)中,這兩個(gè)名字是相同的,在 C++ 函數(shù)中,__PRETTY_FUNCTION__
包括函數(shù)返回類型等額外信息,Linux 內(nèi)核只使用了 __FUNCTION__。
++++ fs/ext2/super.c
98: void ext2_update_dynamic_rev(struct super_block *sb)
99: {
100: struct ext2_super_block *es = EXT2_SB(sb)->s_es;
101:
102: if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
103: return;
104:
105: ext2_warning(sb, __FUNCTION__,
106: "updating to rev %d because of new feature flag, "
107: "running e2fsck is recommended",
108: EXT2_DYNAMIC_REV);
  這里 __FUNCTION__ 將被替換為字符串 "ext2_update_dynamic_rev"。雖然__FUNCTION__
看起來(lái)類似于標(biāo)準(zhǔn) C 中的 __FILE__,但實(shí)際上 __FUNCTION__是被編譯器替換的,不象 __FILE__ 被預(yù)處理器替換。
  內(nèi)建函數(shù)
  GNU C 提供了大量的內(nèi)建函數(shù),其中很多是標(biāo)準(zhǔn) C 庫(kù)函數(shù)的內(nèi)建版本,例如memcpy,它們與對(duì)應(yīng)的 C 庫(kù)函數(shù)功能相同,本文不討論這類函數(shù),其他內(nèi)建函數(shù)的名字通常以 __builtin 開始。
  * __builtin_return_address (LEVEL)
  內(nèi)建函數(shù) __builtin_return_address 返回當(dāng)前函數(shù)或其調(diào)用者的返回地址,參數(shù)LEVEL 指定在棧上搜索框架的個(gè)數(shù),0 表示當(dāng)前函數(shù)的返回地址,1 表示當(dāng)前函數(shù)的調(diào)用者的返回地址,依此類推。例如:
++++ kernel/sched.c
437: printk(KERN_ERR "schedule_timeout: wrong timeout "
438: "value %lx from %p\n", timeout,
439: __builtin_return_address(0));
  * __builtin_constant_p(EXP)
  內(nèi)建函數(shù) __builtin_constant_p 用于判斷一個(gè)值是否為編譯時(shí)常數(shù),如果參數(shù)EXP 的值是常數(shù),函數(shù)返回 1,否則返回 0。例如:
++++ include/asm-i386/bitops.h
249: #define test_bit(nr,addr) \
250: (__builtin_constant_p(nr) ? \
251: constant_test_bit((nr),(addr)) : \
252: variable_test_bit((nr),(addr)))
  很多計(jì)算或操作在參數(shù)為常數(shù)時(shí)有更優(yōu)化的實(shí)現(xiàn),在 GNU C 中用上面的方法可以根據(jù)參數(shù)是否為常數(shù),只編譯常數(shù)版本或非常數(shù)版本,這樣既不失通用性,又能在參數(shù)是常數(shù)時(shí)編譯出最優(yōu)化的代碼。
  * __builtin_expect(EXP, C)
  內(nèi)建函數(shù) __builtin_expect 用于為編譯器提供分支預(yù)測(cè)信息,其返回值是整數(shù)表達(dá)式 EXP 的值,C 的值必須是編譯時(shí)常數(shù)。例如:
++++ include/linux/compiler.h
13: #define likely(x) __builtin_expect((x),1)
14: #define unlikely(x) __builtin_expect((x),0)
++++ kernel/sched.c
564: if (unlikely(in_interrupt())) {
565: printk("Scheduling in interrupt\n");
566: BUG();
567: }
  這個(gè)內(nèi)建函數(shù)的語(yǔ)義是 EXP 的預(yù)期值是
C,編譯器可以根據(jù)這個(gè)信息適當(dāng)?shù)刂嘏耪Z(yǔ)句塊的順序,使程序在預(yù)期的情況下有更高的執(zhí)行效率。上面的例子表示處于中斷上下文是很少發(fā)生的,第
565-566 行的目標(biāo)碼可能會(huì)放在較遠(yuǎn)的位置,以保證經(jīng)常執(zhí)行的目標(biāo)碼更緊湊。
               
               
               

本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/13572/showart_87109.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP