我们知道每个进程运行起来后都有自己独立的虚拟地址空间,这个虚拟地址空间的大小由计算机的硬件平台决定,具体的说是由cpu的位数决定的。硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小,比如32位的硬件平台决定了虚拟空间的地址为0~2的32次方-1,即0x00000000~0xFFFFFFFF,也就是我们常说的4G虚拟空间的大小,而64位的硬件平台具有64位寻址能力,它的虚拟地址空间达到了2的64次方字节,即0x0000000000000000~0xFFFFFFFFFFFFFFFF。
从程序角度而言,我们可以通过判断c语言中指针的所占空间来计算虚拟地址空间的大小。一般来说,c语言指针大小的位数与虚拟地址空间的位数相同,32位平台下的指针为32位,即4字节;64位平台下的指针为64位,即8字节。
下文的讨论中以32位的地址空间为主。
那么32位下的4g虚拟空间,我们的程序是否可以任意使用呢?很遗憾不行,因为程序运行时候处于操作系统的监管下,操作系统为了监控程序运行等一系列目的,进程的虚拟空间都在操作系统的掌控中。进程只能使用操作系统给进程分配的地址,如果访问未经允许的空间,那么操作系统会捕获这些访问,将进程的这种访问视为非法操作,强制结束进程。
我们经常在windows下碰到令人讨厌的“进程因非法操作关闭”或linux地下的“Segmentation fault”很多时候是因为进程访问了未经允许的地址。
那么到底这4G的进程虚拟地址空间是怎样的分配状态呢?首先以linux操作系统作为例子。
也就是说从原则上讲,用户的进程最多使用3G的虚拟地址空间,在整个进程执行的时候,所有的代码,数据,包括通过C语言malloc()等方法申请的虚拟地址空间之和不能超过3G..但是在现实程序中,3G虚拟空间有时候是不够的,那么32位cpu平台下能不能使用超过4G的空间呢?在后面我们会提到。
对于windows操作系统来说,它的进程虚拟地址空间划分是操作系统占2G,进程2G。但是2G空间对于一些程序来说太小了,所以Windows有个启动参数可以将操作系统的虚拟地址空间减少到1G,即跟linux分布一样。win7上的可以自行设置大小。