寫程式對記憶體存取時,需要瞭解兩件事:1. Little Endian與Big Endian在記憶體裡存放的差別;2. 記憶體資料的對齊問題。此篇文章所要探討的即是對齊問題,以現有的計算機(computer)來說,許多計算機均有能力去存取對齊和不對齊在記憶體位址上的資料,
計算機結構-計量方法這本書就解釋得非常清楚,現有一個大小為N的資料存放在某一記憶體位址
A上,只要此位址A除以N且可以被整除的話,就代表此資料是對齊的(aligned):反之就是不對齊的(misaligned),以計算機結構裡的圖可以讓人簡單明瞭 (
註:從白算盤到計算機結構主要都是以MIPS架構作為主題,書中的word代表32位元,但是在x86/x64架構下word則是代表16位元):
|
Fig.1 Aligned and misaligned address.
|
由於計算機是以位元組定址,所以byte存放在任何位址上均是對齊在byte boundary上,但若是half word, word或double world的話,就會有對齊和不對齊的問題,若要能夠存取非對齊的資料,計算機的設計也會變得比較複雜。既然有些計算機均可存取對齊和不對齊的資料,那對不對齊又有何差別? 答案當然是有差別的,以不對齊的資料來說,計算機會存取的比已經對齊好的資料還要慢,所以編譯器通常會將程式碼的資料做對齊處理,為了讓人有更深入的感受,在此宣告一結構說明:
struct AlignedStruct{
uint8_t uint8Var1;
uint64_t uint64Var2;
uint8_t uint8Var3;
uint16_t uint16Var4;
uint8_t uint8Var5;
uint32_t uint32Var6;
uint64_t uint64Var7;
uint32_t uint32Var8;
};
uint64_t getAlignedAddress(uint64_t currentElementAddr,uint16_t currentElementSize,uint16_t nextElementSize){
uint64_t address = currentElementAddr + currentElementSize;
for(;;){
if((address%nextElementSize) == 0)
break;
else
address ++;
}
return address;
}
getAlignedAddress()是根據上述說明,用來計算下一筆資料的對齊位址,第二行算出下一筆資料的起始位址,由於無法肯定此位址是不是對齊好的位址,所以第四到第九行用來計算下一筆資料的實際對齊位址。因此AlignedStruct結構在記憶體裡的排放方式如Fig. 2所顯示的樣子:
|
Fig.2 Struct layout in the memory space. |
目前為止都是根據理論來說明,下例的程式碼用來確認實際上的狀況:
待補...
沒有留言:
張貼留言