日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

SECTIONS bss段初始化分析

發(fā)布時間:2023/11/28 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SECTIONS bss段初始化分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

SECTIONS bss段初始化分析
都知道bss段需要初始化,但是這是為什么呢?
通過瀏覽資料,都會發(fā)現(xiàn),bss段是不會出現(xiàn)在程序下載文件(*.bin .hex)中的,因?yàn)槿际?。如果把出現(xiàn)在程序下載文件中,會增加程序下載文件的大小。實(shí)際應(yīng)用中,通常只需要把bss段的起始地址和結(jié)束地址保存起來,而不需要將程序下載文件中出現(xiàn)bss段(一堆0)將來真正運(yùn)行程序的時候,再根據(jù)這兩個數(shù)據(jù)進(jìn)行bss段的初始化就行了。
以上這段文字是網(wǎng)上的資料說的。但是,可不可以讓bss段出現(xiàn)在程序下載文件中呢?如果這樣可以的話,當(dāng)程序由存儲器(例如nandflash)拷貝到內(nèi)存中時,捎帶著會把bss段像data段那樣初始化。
實(shí)際上是可以這樣做的。看下邊的兩個鏈接腳本。
鏈接腳本一:
SECTIONS {
. = 0x00000000;
.init : AT(0){ head.o init.o nand.o}
. = 0x30000000;
.text : AT(4096) { (.text) }
.rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {
(.rodata
)}
.data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
__bss_start = .;
.bss ALIGN(4) : { *(.bss) (COMMON) }
__bss_end = .;
}
鏈接腳本二:
SECTIONS {
. = 0x00000000;
.init : AT(0){ head.o init.o nand.o}
. = 0x30000000;
.text : AT(4096) { (.text) }
.rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {
(.rodata
)}
.bss ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)){ *(.bss) }
.data ALIGN(4) : AT((LOADADDR(.bss)+SIZEOF(.bss)+3)&~(0x03)) { *(.data) }
}
鏈接腳本一,把bss段放在最后邊,arm-linux-gcc編譯器默認(rèn)的會把bss段給忽略掉,也即不會讓bss段出現(xiàn)在程序下載文件中(可以通過Jlink軟件查看編譯后的bin文件)。這種鏈接腳本也是通常見到的方式。
鏈接腳本二,把bss段放在了rodata段和data段中間,這個時候,arm-linux-gcc編譯器并不會把bss段在程序下載文件中刪除,也即會把bss段保留下來,最終出現(xiàn)在程序下載文件中。考慮原因可能是這樣的:編譯后的地址rodata段、bss段、data段是連續(xù)的,也即程序運(yùn)行時這幾個段是連續(xù)的;倘若把bss段在程序下載文件中刪除,那么程序下載文件中rodata段后邊緊接著的是data段;這就要求程序的這兩個段需要分別處理,而不能一次性將連續(xù)拷貝過去。
鏈接腳本二的方法可以讓bss段出現(xiàn)在程序下載文件中。但是,通常都不會這樣做,這里之所以這樣深鉆,只不過是在探究bss段初始化的必要性。通常采用的鏈接腳本一,由于最終程序下載文件中沒有bss段,所以必須在應(yīng)用程序運(yùn)行前,根據(jù)bss段的起始地址和結(jié)束地址將bss段初始化。
下邊,著重講一下鏈接腳本中與初始化bss段相關(guān)的幾句話。
(1) __bss_start = .;
(2).bss ALIGN(4) : { *(.bss) *(COMMON) }
(3)__bss_end = .;
實(shí)際上句(1)是在bss段的起始地址處定義了一個int類型的全局變量__bss_start。雖然,bss段的起始地址處肯定是一個未初始化的全局變量,但是這里算是編譯器又在這個位置上又重新定義了一個全局變量。就是說,一個地址有兩個名字,都能訪問這個地址空間。句(3)的解釋同句(1)。
接著再看一下用C語言寫的初始化bss段的程序。
(1)void clean_bss(void)
(2){
(3) extern int __bss_start, __bss_end;
(4) int *p = &__bss_start;
(5)
(6) for (; p < &__bss_end; p++)
(7) *p = 0;
(8)}
首先,句(3)對編譯器產(chǎn)生的兩個全局變量進(jìn)行聲明。句(4)通過__bss_start取出bss段的起始地址,句(6)通過__bss_end取出bss段的結(jié)束地址。

參考鏈接:
https://www.cnblogs.com/amanlikethis/p/3384743.html

總結(jié)

以上是生活随笔為你收集整理的SECTIONS bss段初始化分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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