一,前言
使用64位体系结构对应用程序的开发者来说,Solaris 64位操作系统和32位操作系统之间的最大差别在于它们使用的C语言数据类型模型。64位操作系统使用LP64模型,在LP64模型中long类型和指针类型是64位的。其他基本数据类型和32位的模型一样。32位数据类型使用ILP32模型,其中的int,long和指针类型都是32位的。下面列出了64位环境的主要特点和使用时需要考虑的问题。l 巨大的虚拟地址空间在64位环境中,一个进程可以有多达64位宽的虚拟地址空间,或18 exabytes(18*260字节)。这是32位环境中4G虚拟地址空间的四十亿倍。由于硬件的限制,有的64位平台无法完全支持64位的地址空间。大地址空间使得系统可以创建更多的线程,在32位平台上一个缺省的线程需要1M堆栈,在64位平台上一个缺省的线程需要2M堆栈。在32位平台上可以创建4000个缺省线程,在64位平台上可以创建8万亿个缺省线程。l 使用核心内存的程序由于系统核心内部也使用64位的数据结构,所以现存的程序,如果使用了libkvm,/dev/mem或/dev/kmem,将无法再在64位环境中运行。必须将这样的程序转变为64位的程序。l /proc的限制一个使用/proc的32位应用程序可以访问32位进程的属性,但无法访问一个64位进程的属性;现存的描述进程的接口和数据结构不能包含所涉及的64位的量。这种程序必须重新编译成64位应用程序,这样才能访问32位和64位进程的属性。l 64位库32位的应用程序必须和32位的库链接在一起,64位的应用程序必须和64位的库链接在一起。除了过时的库,所有的库都有32位和64位两种版本。但没有一个64位库是静态链接库。l 64位运算尽管在32位的Solaris系统中已经有64位运算了,但64位的实现为整数操作和参数传递提供了完全64位的机器寄存器。l 大文件如果一个程序只需要支持大文件,使用32位Solaris的大文件接口就可以了。但是为了充分的利用64位的优点,最好把程序转变为64位代码。
64 位计算
Red Hat 和很多其它发行商为 Compaq/DEC Alpha 提供了一种 64 位版的 Linux。您可以在 AlphaLinux Web 站点上了解关于这种 Linux 的其它信息。64 位的 Solaris 和 64 位的 Linux/Alpha 都使用 LP64 数据模型,它能够带来很好的兼容性。
不久,Intel Itanium(TM) IA-64 处理器也能使用一种 64 位版的 Linux。您可以在 IA-64 Linux Project Web 站点了解关于这种 Linux 的更多信息。一种支持 IBM 64 位 PowerPC 体系结构的 Linux 也在开发之中。
请注意,尽管 SuSE Linux/UltraSPARC 的内核运行在 64 位的模式中,但 SuSE Linux/UltraSPARC 目前并不支持 64 位的用户空间应用程序。
二,对于hp 32bit位 和64bit的区别
hp C/HP-UX 32-bit and 64-bit base data types |
||
data type |
ILP32 size (bits) |
LP64 size (bits) |
char |
8 |
8 |
short |
16 |
16 |
int |
32 |
32 |
long |
32 |
64 |
long long(1) |
64 |
64 |
pointer |
32 |
64 |
float |
32 |
32 |
double |
64 |
64 |
long double |
128 |
128 |
enum(2) |
32 |
32 |
最主要的区别是long型和pointer型数据。
三,32bit机数据在内容中的说明
A) 在为变量/对象分配内存的时候,总是以4字节对齐,无论你的变量类型是什么。也就是说,任何一个变量/对象的存储空间都是以4的整数倍的地址开始的。
B) 对于pointer型数据,因为内容是地址,要求该地址也必须是4整数倍。
C) 例如:
main()
{
struct student
{
int i;
long l;
}node;
struct student *p;
p=&node;
int *pp;
char *qq;
long *ll;
p->i=1;
p->l=2;
pp=(int *)p;
qq=(char *)p;
ll=(long *)p;
printf("int pp l=%d/n",*(pp+1)); /*result =2*/
printf("char qq l=%d/n",*(qq+7)); /*result =2*/
(char型指针指向的内容只能是1字节的数据。如果将
p->l赋更大的值22222,*(qq+7))只能取到地址为0x200000007ffff657
对应的内容)
printf("long ll l=%d/n",*(ll+1)); /*result =2*/
}
结构体的内存分配如下:
0x200000007ffff650: 0x00000001 0x00000002 0x00000000 0x00000000
0x200000007ffff660: 0x00000190 0x000002ec 0x000017a0 0x00000002
0x200000007ffff670: 0x00000000 0x00000000
图解如下:
|
data |
|
0x200000007ffff650 |
00 |
|
0x200000007ffff651 |
00 |
|
0x200000007ffff652 |
00 |
|
0x200000007ffff653 |
01 |
|
0x200000007ffff654 |
|
|
0x200000007ffff655 |
00 |
|
0x200000007ffff656 |
00 |
|
0x200000007ffff657 |
02 |
|
0x200000007ffff658 |
|
|
0x200000007ffff659 |
|
|
0x200000007ffff65A |
|
i |
四,64bit机数据在内容中的说明
A) 在为变量/对象分配内存的时候,总是以8字节对齐,无论你的变量类型是什么。也就是说,任何一个变量/对象的存储空间都是以8的整数倍的地址开始的。
B) 对于pointer型数据,因为内容是地址,要求该地址也必须是8整数倍。
C) 例如:
main()
{
struct student
{
int i; /*8个字节的存储空间,*/
long l; /*8个字节的存储空间,*/
}node;
struct student *p;
p=&node;
int *pp;
char *qq;
long *ll;
p->i=1;
p->l=222222222;
pp=(int *)p;
qq=(char *)p;
ll=(long *)p;
printf("int pp l=%d/n",*(pp+2));/*result int pp l=222222222*/
printf("char qq l=%d/n",*(qq+15));/*result int pp 13*/
printf("long ll l=%d/n",*(ll+1));/*result int pp l=222222222*/
}
五,64bit机下,内存对齐的例子
正确:
int main()
{
long i;
char a[44];
long *p;
p=(char *)(a+8);
*p=3;
printf("*p=%d/n",*p); /*result = 3*/
}
错误:
void main()
{
long i;
char a[44];
long *p;
p=a+4;
*p=3;
printf("*p=%d/n",*p); /*bus error*/
}
六,程序中的内存分配浅谈
一.存空间的对齐规则
首先看一段例子:
……
int i1;
char c1;
char c2;
int i2;
cout << "i1:" <<&i1 << "/n";
cout << "c1:" <<(void *)&c1 << "/n";
cout << "c2:" <<(void *)&c2 << "/n";
cout << "i2:" <<&i2 << "/n";
……
输出结果如下:
i1:0012FF4C
c1:0012FF48
c2:0012FF44
i2:0012FF40
是不是有些奇怪?
我们知道char类型的变量是只占用一个字节的,用sizeof(char)得到的结果也会是1。但在这里我们看到,c1和c2都被分配了4个字节的存储空间,在32bit机下,在为变量/对象分配内存的时候,总是以4字节对齐,无论你的变量类型是什么。也就是说,任何一个变量/对象的存储空间都是以4的整数倍的地址开始的。64bit机下,都是8的倍数。