GNU C - 關於8086的內存訪問機制以及內存對齊(memory alignment)


接着前面的文章,這篇文章就來說說menory alignment -- 內存對齊.

 

一、為什么需要內存對齊?

 

無論做什么事情,我都習慣性的問自己:為什么我要去做這件事情? 是啊,這可能也是個大家都會去想的問題,

因為我們都不能稀里糊塗的或者。那為什么需要內存對齊呢?這要從cpu的內存訪問機制說起.

 

為了了解清楚cpu的內存訪問機制,昨天整晚都在查找資料,但是還是找不到很好的介紹資料.后來只是找到了相關

的一些介紹的博客。 這些博客中大多都是以介紹內存對齊為主要目的,然后順帶着說一下cpu的內存訪問機制,所以

找不到權威的資料,后來聽說<<匯編語言編程藝術>>這本書里面有關於x86的系統介紹,就下載了一份PDF,但是

也還是沒有找到.

 

所以呢下面的一些關於x86的內存訪問方面的只是很多都是來源於一些比較好的博客.在文章的最后我會注明參考的

博客鏈接,作為擴展閱讀.

 

簡單介紹x86的內存訪問機制:

1.內存的寫入操作: cpu把需要寫入的地址放入地址總線, 把需要寫入的數據放入數據總線, 把控制總線置為寫入操作.

         然后內存子系統根據地址總線選定內存單元, 檢查控制總線發現是寫入操作,則入去數據總線數據, 寫入相關內存

         單元.

 

2.內存的讀入操作: cpu把需要讀入的地址放入地址總線, 把控制總線置為讀入操作. 內存子系統根據地址總線選定內存

         單元, 檢查控制總線發現是讀入操作, 則讀取內存單元中的數據, 寫入數據總線.

 

 16bit數據總線: 每個內存周期,cpu只能讀取一個偶單元和一個奇單元,地址總線的地址是偶單元的地址,所以地址總線的地址永遠是2對齊的.

        每個內存周期,可以讀取一個字,也就是16bit.

   1.讀取一個字,如果是以2對齊的,則只需要一個內存周期即可完成.如果數據不是以2對齊的,則需要2個內存周期.

   2.讀取雙字: 如果是以2對齊的,則只需要2個內存周期即可完成,如果數據不是以2對齊的,則需要3個內存周期完成.

 

32bit數據總線: 每個內存周期,讀取的數據地址都是以4對齊的.一個內存周期可以讀取一個雙字,也就是32bit.

    1.如果讀取一個雙字,地址是以4對齊的話,則只需要一個內存周期即可完成.如果不是以4對齊,則需要2個內存周期完成.

    2.如果讀取一個字,地址是對4取模余3的話,那么需要2個內存周期完成對數據的讀取.地址如果對4去模不余3的話,則

       只需要一個內存周期即可完成數據讀取.

    3. 對於字節, 任何字節地址讀取只需要一個內存周期.

 

通過上面可以看得出,為什么16bit數據總線cpu是以2對齊的,而32bit數據總線cpu是以4對齊的. 最主要的原因是能夠在最小的

內存周期內完成對地址的訪問,提高cpu的效率.

 

二、內存對齊的作用

   如果不采用內存對齊機制的話,有些地址的訪問需要在多個內存周期內完成,而且還需要多次內存周期讀取的高低字節

進行拼湊,然后得到32bit數據.  如果使用內存對齊機制,不僅可以減少對地址訪問過程中需要的內存周期,而且還避免了

高低字節的數據拼湊,提高了cpu的工作效率.

 

三、編譯器是如何處理內存對齊的?

 

struct mem_alignment
{
   char     a;

   int      b;

   char     c;
};

 

 

 在32位x86機器上面它的大小是12. 另外一個問題,如果結構體中的成員變量順序不一樣會導致該結構在內存中的長度

 也不一樣,就像上面,如果改成下面這個樣子:

 

struct mem_alignment
{
   char     a;

   char     c;

   int      b;
};

 

 那么它的大小就變成了8.

 

 如果我們使用緊湊的對齊方式 __attribute__((packed)) or  __attribute__((aligned (1)))的話,

 那么struct mem_alignment的大小應該是6. 或者是使用偽指令#pragma pack (1).

 

#pragma pack (1)

struct mem_alignment
{
   char     a;

   char     c;

   int      b;
};

#pragma pack () 

 

 

  上面最后一句的作用是恢復編譯器默認的對齊方式.

 
關於內存對齊方面的知識就總結到這里. 也算是對前面文章的交代了~

 

參考資料:

          <<從80X86結構看內存對齊問題>> http://my.unix-center.net/~Simon_fu/?p=262

          <<oschina 內存對齊的問題>>  http://www.oschina.net/question/234345_48055

          <<Thinking in linux C/C++字節對齊詳解>> http://www.linuxsong.org/2010/09/c-byte-alignment/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM