在看android AOSP時看到這樣一行代碼
unsigned int __atags_pointer __initdata
__atags_pointer是Uboot傳遞給kernel的設(shè)備樹首地址
這里定義了一個無符號整形拳芙,將用到它表示一個地址,但是后面__initdata代表什么呢?
引用內(nèi)核中的宏定義__init,__initdata,_exitdata程序猿Ricky的日常干貨的博客-CSDN博客
在linux內(nèi)核中,我們經(jīng)常會使用到一些宏定義,比如__init,__initdata,__exitdata等等砍濒。那么這些宏定義到底什么意思呢?接下來我們就來看一下元咙。
kernel/include/linux/init.h:
我們來選擇一些常用的宏定義梯影,在路徑:/vendor/nxp-opensource/kernel_imx/include/linux/init.h下巫员,有如下代碼:
50 #define __init __section(".init.text") __cold __latent_entropy __noinitretpoline __nocfi
51 #define __initdata __section(".init.data")
52 #define __initconst __section(".init.rodata")
53 #define __exitdata __section(".exit.data")
54 #define __exit_call __used __section(".exitcall.exit")
我們可以看到大多是和section相關(guān)的定義庶香,這個段定義什么作用呢,它是為了告訴鏈接器應(yīng)該把這個函數(shù)或者數(shù)據(jù)放置在哪個位置简识。一般是指放置到內(nèi)核鏡像的哪個位置上赶掖。內(nèi)核相當于一個非常大的可執(zhí)行程序感猛,它里面包含了好多內(nèi)容,我們按照分段的原則來存放這些內(nèi)容奢赂。具體段的存放規(guī)則是由vmlinux.lds文件定義陪白,它是負責把段信息告訴鏈接器的,當然我們也要在代碼中聲明屬于哪個段膳灶。
通常編譯器將函數(shù)放在.text 節(jié)咱士,變量放在.data 或 .bss 節(jié),使用 section 屬性轧钓,可以讓編譯器將函數(shù)或變量放在指定的節(jié)中序厉。那么例如:前面對__init 的定義便表示將它修飾的代碼放在.init.text節(jié)。內(nèi)核把段分的非常細致毕箍,是因為它會在運行過程中去定位相應(yīng)的數(shù)據(jù)和代碼弛房,這樣將更加方便處理。就像__init 修飾的所有代碼都放在.init.text段而柑,它只在啟動階段會被內(nèi)核調(diào)用到文捶,當初始化結(jié)束后就會釋放這部分內(nèi)存,以便充分利用內(nèi)存媒咳,這個就是屬于內(nèi)存管理的部分了粹排。
C代碼中一般是按照這種規(guī)則來傳遞段信息的
__attribute__((section("section_name")))
可是上面的定義并不是如此,其實__section也是一個宏定義涩澡,我們在/vendor/nxp-opensource/kernel_imx/include/linux/compiler_attributes.h下可以看到
267 #define __section(section) __attribute__((__section__(section)))
至于匯編代碼我們就都很清楚了恨搓,直接使用.section即可。