大内高手—内存模型
来源:互联网 发布:linux中 dump函数 编辑:程序博客网 时间:2024/04/30 02:05
大内高手—内存模型
了解linux的内存模型,或许不能让你大幅度提高编程能力,但是作为一个基本知识点应该熟悉。坐火车外出旅行时,即时你对沿途的地方一无所知,仍然可以到达目标地。但是你对整个路途都很比较清楚的话,每到一个站都知道自己在哪里,知道当地的风土人情,对比一下所见所想,旅程可能更有趣一些。
类似的,了解linux的内存模型,你知道每块内存,每个变量,在系统中处于什么样的位置。这同样会让你心情愉快,知道这些,有时还会让你的生活轻更松些。看看变量的地址,你可以大致断定这是否是一个有效的地址。一个变量被破坏了,你可以大致推断谁是犯罪嫌疑人。
Linux的内存模型,一般为:
地址
作用
说明
>=0xc000 0000
内核虚拟存储器
用户代码不可见区域
<0xc000 0000
Stack(用户栈)
ESP指向栈顶
↓
↑
空闲内存
>=0x4000 0000
文件映射区
<0x4000 0000
↑
空闲内存
Heap(运行时堆)
通过brk/sbrk系统调用扩大堆,向上增长。
.data、.bss(读写段)
从可执行文件中加载
>=0x0804 8000
.init、.text、.rodata(只读段)
从可执行文件中加载
<0x0804 8000
保留区域
很多书上都有类似的描述,本图取自于《深入理解计算机系统》p603,略做修改。本图比较清析,很容易理解,但仍然有两点不足。下面补充说明一下:
1. 第一点是关于运行时堆的。
为说明这个问题,我们先运行一个测试程序,并观察其结果:
#include <stdio.h>
int main(int argc, char* argv[])
{
int first = 0;
int* p0 = malloc(1024);
int* p1 = malloc(1024 * 1024);
int* p2 = malloc(512 * 1024 * 1024 );
int* p3 = malloc(1024 * 1024 * 1024 );
printf("main=%p print=%p/n", main, printf);
printf("first=%p/n", &first);
printf("p0=%p p1=%p p2=%p p3=%p/n", p0, p1, p2, p3);
getchar();
return 0;
}
运行后,输出结果为:
main=0x8048404 print=0x8048324
first=0xbfcd1264
p0=0x9253008 p1=0xb7ec0008 p2=0x97ebf008 p3=0x57ebe008
l main和print两个函数是代码段(.text)的,其地址符合表一的描述。
l first是第一个临时变量,由于在first之前还有一些环境变量,它的值并非0xbfffffff,而是0xbfcd1264,这是正常的。
l p0是在堆中分配的,其地址小于0x4000 0000,这也是正常的。
l 但p1和p2也是在堆中分配的,而其地址竟大于0x4000 0000,与表一描述不符。
原因在于:运行时堆的位置与内存管理算法相关,也就是与malloc的实现相关。关于内存管理算法的问题,我们在后继文章中有详细描述,这里只作简要说明。在glibc实现的内存管理算法中,Malloc小块内存是在小于0x4000 0000的内存中分配的,通过brk/sbrk不断向上扩展,而分配大块内存,malloc直接通过系统调用mmap实现,分配得到的地址在文件映射区,所以其地址大于0x4000 0000。
从maps文件中可以清楚的看到一点:
00514000-00515000 r-xp 00514000 00:00 0
00624000-0063e000 r-xp 00000000 03:01 718192 /lib/ld-
0063e000
00642000-00766000 r-xp 00000000 03:01 718193 /lib/libc-
00766000-00768000 r-xp 00124000 03:01 718193 /lib/libc-
00768000
08048000-08049000 r-xp 00000000 03:01 1307138 /root/test/mem/t.exe
08049000
57e
b
bfb
2. 第二是关于多线程的。
现在的应用程序,多线程的居多。表一所描述的模型无法适用于多线程环境。按表一所述,程序最多拥有上G的栈空间,事实上,在多线程情况下,能用的栈空间是非常有限的。为了说明这个问题,我们再看另外一个测试:
#include <stdio.h>
#include <pthread.h>
void* thread_proc(void* param)
{
int first = 0;
int* p0 = malloc(1024);
int* p1 = malloc(1024 * 1024);
printf("(0x%x): first=%p/n", pthread_self(), &first);
printf("(0x%x): p0=%p p1=%p /n", pthread_self(), p0, p1);
return 0;
}
#define N 5
int main(int argc, char* argv[])
{
int first = 0;
int i= 0;
void* ret = NULL;
pthread_t tid[N] = {0};
printf("first=%p/n", &first);
for(i = 0; i < N; i++)
{
pthread_create(tid+i, NULL, thread_proc, NULL);
}
for(i = 0; i < N; i++)
{
pthread_join(tid[i], &ret);
}
return 0;
}
运行后,输出结果为:
first=0xbfd3d
(0xb
(0xb
(0xb752bbb0): first=0xb752b454
(0xb752bbb0): p0=0x84d56e0 p1=0xb4b26008
(0xb6b2abb0): first=0xb6b
(0xb6b2abb0): p0=0x84d5ae8 p1=0xb
(0xb6129bb0): first=0xb6129454
(0xb6129bb0): p0=0x84d5ef0 p1=0xb4924008
(0xb5728bb0): first=0xb5728454
(0xb5728bb0): p0=0x84d
我们看一下:
主线程与第一个线程的栈之间的距离:0xbfd3d
第一个线程与第二个线程的栈之间的距离:0xb
其它几个线程的栈之间距离均为
也就是说,主线程的栈空间最大为
栈溢出的后果是比较严重的,或者出现Segmentation fault错误,或者出现莫名其妙的错误。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=814268
[点击此处收藏本文] absurd发表于
cquzjh 发表于2006-06-23 10:15:00 IP: 220.167.25.*
我们看一下:
主线程与第一个线程的堆之间的距离:0xbfd3d35c - 0xb7f2c454=0x7e10f08=126M
第一个线程与第二个线程的堆之间的距离:0xb7f2c454 - 0xb752b454=0xa01000=10M
其它几个线程间的距离均为10M。
也就是说,主线程的堆空间最大为126M,而普通线程的栈空间仅为10M,超这个范围就会造成栈溢出。
这一段有笔误,应该是栈空间吧!~
x86_64 发表于2006-06-23 11:01:00 IP: 222.51.246.*
我的输出结果如下:
first=0x7fff084618e8
(0x40800950): first=0x408001bc
(0x40800950): p0=0x5015b0 p1=0x2aaaaaaab010
(0x41001950): first=0x410011bc
(0x41001950): p0=0x5019c0 p1=0x2aaaaabac010
(0x41802950): first=0x418021bc
(0x41802950): p0=0x501dd0 p1=0x2aaaaacad010
(0x42003950): first=0x420031bc
(0x42003950): p0=0x5021e0 p1=0x2aaaaadae010
(0x42804950): first=0x428041bc
(0x42804950): p0=0x5025f0 p1=0x2aaaaaeaf010
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型
- 大内高手—内存模型[转帖]
- 转载--大内高手—内存模型
- 大内高手—全局内存
- 大内高手—内存管理器
- 大内高手—全局内存
- 大内高手—内存管理器
- Tony说世界杯之八强预测篇
- 关于JPEG编码的感想
- 谈Delphi中LocalObject内存分配的优化
- 富兰克林的美德观,值得学习
- 大内高手—序
- 大内高手—内存模型
- 格式化字符串
- 一个软件工作者给前女友的最后一封信
- 老婆使用说明书:)
- 数据仓库研究之三--JPivot入门
- Structs的深入研究
- zt日本人为何瞧不起中国人?
- VC中的一些常用方法
- zt我能理解日本人为什么瞧不起中国人