日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

linux内核 extern,Linux内核之_attribute_

發(fā)布時間:2025/3/19 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核 extern,Linux内核之_attribute_ 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

GCC 的一大特色就是__attribute__機制。

__attribute__可以設置函數(shù)屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)。

attribute前后都有兩個下劃線,后面會緊跟一對原括弧,括弧里面是相應的__attribute__參數(shù)。

語法格式為:__attribute__ ((attribute-list))

其位置約束為:放于聲明尾部“;”之前。

函數(shù)屬性(Function Attribute)

函數(shù)屬性可以幫助開發(fā)者把一些特性添加到函數(shù)聲明中,從而可以使編譯器在錯誤檢查方面的功能更強大

__attribute__ format

該__attribute__屬性可以給被聲明的函數(shù)加上類似printf或者scanf的特征,它可以使編譯器檢查函數(shù)聲明和函數(shù)實際調用參數(shù)之間的格式化字符串是否匹配。該功能十分有用,尤其是處理一些很難發(fā)現(xiàn)的bug。

format的語法格式為:

format (archetype, string-index, first-to-check)

format屬性告訴編譯器,按照printf, scanf, strftime或strfmon的參數(shù)表格式規(guī)則對該函數(shù)的參數(shù)進行檢查。“archetype”指定是哪種風格;“string-index”指定傳入函數(shù)的第幾個參數(shù)是格式化字符串;“first-to-check”指定從函數(shù)的第幾個參數(shù)開始按上述規(guī)則進行檢查。

具體使用格式如下:

__attribute__((format(printf,m,n)))

__attribute__((format(scanf,m,n)))

其中參數(shù)m與n的含義為:

m:第幾個參數(shù)為格式化字符串(format string);

n:參數(shù)集合中的第一個,即參數(shù)“…”里的第一個參數(shù)在函數(shù)參數(shù)總數(shù)排在第幾,注意,有時函數(shù)參數(shù)里還有“隱身”的呢,后面會提到;

在使用上,__attribute__((format(printf,m,n)))是常用的,而另一種卻很少見到。下面舉例說明,其中myprint為自己定義的一個帶有可變參數(shù)的函數(shù),其功能類似于printf:

//m=1;n=2

extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));

//m=2;n=3

extern void myprint(int l,const char *format,...) __attribute__((format(printf,2,3)));

需要特別注意的是,如果myprint是一個函數(shù)的成員函數(shù),那么m和n的值可有點“懸乎”了,例如:

//m=3;n=4

extern void myprint(int l,const char *format,...) __attribute__((format(printf,3,4)));

其原因是,類成員函數(shù)的第一個參數(shù)實際上一個“隱身”的“this”指針。(有點C++基礎的都知道點this指針,不知道你在這里還知道嗎?)

__attribute__ noreturn

該屬性通知編譯器函數(shù)從不返回值,當遇到類似函數(shù)需要返回值而卻不可能運行到返回值處就已經(jīng)退出來的情況,該屬性可以避免出現(xiàn)錯誤信息。C庫函數(shù)中的abort()和exit()的聲明格式就采用了這種格式,如下所示:

extern void exit(int) __attribute__((noreturn));

extern void abort(void) __attribute__((noreturn));

__attribute__ const

該屬性只能用于帶有數(shù)值類型參數(shù)的函數(shù)上。當重復調用帶有數(shù)值參數(shù)的函數(shù)時,由于返回值是相同的,所以此時編譯器可以進行優(yōu)化處理,除第一次需要運算外,其它只需要返回第一次的結果就可以了,進而可以提高效率。該屬性主要適用于沒有靜態(tài)狀態(tài)(static state)和副作用的一些函數(shù),并且返回值僅僅依賴輸入的參數(shù)。

為了說明問題,下面舉個非常“糟糕”的例子,該例子將重復調用一個帶有相同參數(shù)值的函數(shù),具體如下:

extern int square(int n) __attribute__((const));

for (i = 0; i < 100; i++ )

{

total += square(5) + i;

}

通過添加__attribute__((const))聲明,編譯器只調用了函數(shù)一次,以后只是直接得到了相同的一個返回值。

同時使用多個屬性

可以在同一個函數(shù)聲明里使用多個__attribute__,并且實際應用中這種情況是十分常見的。使用方式上,你可以選擇兩個單獨的__attribute__,或者把它們寫在一起,可以參考下面的例子:

extern void die(const char *format, ...)

__attribute__((noreturn))

__attribute__((format(printf, 1, 2)));

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 內核很喜歡使用這種技術,

例如系統(tǒng)的初始化代碼被安排在單獨的一個節(jié),在初始化結束后就可以釋放這部分內存。

* aligned (ALIGNMENT)

屬性 aligned 用于變量、結構或聯(lián)合類型,指定變量、結構域、結構或聯(lián)合的對齊量,以字節(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)));

表示該結構類型的變量以 16 字節(jié)對齊。通常編譯器會選擇合適的對齊量,顯示指

定對齊通常是由于體系限制、優(yōu)化等原因。

* packed

屬性 packed 用于變量和類型,用于變量或結構域時表示使用最小可能的對齊,用

于枚舉、結構或聯(lián)合類型時表示該類型使用最小的內存。例如:

++++ include/asm-i386/desc.h

51: struct Xgt_desc_struct {

52: unsigned short size;

53: unsigned long address __attribute__((packed));

54: };

域 address 將緊接著 size 分配。屬性 packed 的用途大多是定義硬件相關的結

構,使元素之間沒有因對齊而造成的空洞。

當前函數(shù)名

==========

GNU CC 預定義了兩個標志符保存當前函數(shù)的名字,__FUNCTION__ 保存函數(shù)在源碼

中的名字,__PRETTY_FUNCTION__ 保存帶語言特色的名字。在 C 函數(shù)中,這兩個

名字是相同的,在 C++ 函數(shù)中,__PRETTY_FUNCTION__ 包括函數(shù)返回類型等額外

信息,Linux 內核只使用了 __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__ 看起來類似于標準 C 中的 __FILE__,但實際上 __FUNCTION__

是被編譯器替換的,不象 __FILE__ 被預處理器替換。

內建函數(shù)

GNU C 提供了大量的內建函數(shù),其中很多是標準 C 庫函數(shù)的內建版本,例如

memcpy,它們與對應的 C 庫函數(shù)功能相同,本文不討論這類函數(shù),其他內建函數(shù)

的名字通常以 __builtin 開始。

* __builtin_return_address (LEVEL)

內建函數(shù) __builtin_return_address 返回當前函數(shù)或其調用者的返回地址,參數(shù)

LEVEL 指定在棧上搜索框架的個數(shù),0 表示當前函數(shù)的返回地址,1 表示當前函數(shù)

的調用者的返回地址,依此類推。例如:

++++ 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)

內建函數(shù) __builtin_constant_p 用于判斷一個值是否為編譯時常數(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)))

很多計算或操作在參數(shù)為常數(shù)時有更優(yōu)化的實現(xiàn),在 GNU C 中用上面的方法可以

根據(jù)參數(shù)是否為常數(shù),只編譯常數(shù)版本或非常數(shù)版本,這樣既不失通用性,又能在

參數(shù)是常數(shù)時編譯出最優(yōu)化的代碼。

* __builtin_expect(EXP, C)

內建函數(shù) __builtin_expect 用于為編譯器提供分支預測信息,其返回值是整數(shù)表

達式 EXP 的值,C 的值必須是編譯時常數(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: }

這個內建函數(shù)的語義是 EXP 的預期值是 C,編譯器可以根據(jù)這個信息適當?shù)刂嘏?/p>

語句塊的順序,使程序在預期的情況下有更高的執(zhí)行效率。上面的例子表示處于中

斷上下文是很少發(fā)生的,第 565-566 行的目標碼可能會放在較遠的位置,以保證

經(jīng)常執(zhí)行的目標碼更緊湊。

總結

以上是生活随笔為你收集整理的linux内核 extern,Linux内核之_attribute_的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。