GNU C - 关于8086的内存访问机制以及内存对齐(memory alignment)
来源:互联网 发布:linux 端口查看 编辑:程序博客网 时间:2024/05/19 03:43
一、为什么需要内存对齐?
无论做什么事情,我都习惯性的问自己:为什么我要去做这件事情? 是啊,这可能也是个大家都会去想的问题,
因为我们都不能稀里糊涂的或者。那为什么需要内存对齐呢?这要从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/
- GNU C - 关于8086的内存访问机制以及内存对齐(memory alignment)
- 8086架构的CPU的内存访问机制以及内存对齐(memory alignment)
- 内存对齐(Memory Alignment)
- C++类的内存对齐-C++alignment
- 不可不知的内存对齐(Memory Alignment)
- VC内存对齐准则(Memory alignment)
- VC内存对齐准则(Memory alignment)
- 内存对齐 alignment
- 内存对齐 alignment
- C语言的内存对齐机制
- ARM Linux中的非对齐内存访问(Alignment trap警告的原因)
- ARM Linux中的非对齐内存访问(Alignment trap警告的原因)
- GNU 内存对齐
- 关于C语言 内存对齐的问题
- 内存对齐(memory aligment)
- 关于C语言内存对齐
- OpenCV的内存对齐机制
- OpenCV的内存对齐机制
- 数据库检索中,使用exists时,还是配合distinct 来得快。
- note
- SOURCES的文件格式
- 笔试题
- ch_7.02
- GNU C - 关于8086的内存访问机制以及内存对齐(memory alignment)
- 黑马程序员--JAVA之内省、注解与类加载器
- 总结Objective-C中CGGeometry 几何类的常用方法
- C#控制台应用程序Main函数中的参数args
- 塞班领先地位如何被苹果迅速摧毁?
- 如何在javaweb项目中引入jquery库函数,以及如何使用
- WTL 工具条摆放非Button资源
- 红黑树的介绍和实现(一)[原创]
- IOS使用 swizzle 解决一些错误