Linux的内存模型,一般为:

现在的每个进程使用了全部4G线性空间。在加载程序时内核把程序加载到线性地址0x08048000开始的位置。这个位置当然>128MB。2G开始是共享库,3G开始是内核。

地址------------------------作用--------------------------说明

>=0xc0000000---------内核虚拟存储器-------------用户代码不可见区域

< 0xc0000000----------Stack(用户栈)------------ESP指向栈顶,向下增长

-------------------------------------------------空闲内存

>=0x40000000---------文件映射区------------------mmap的空间

< 0x40000000-------------------------------------空闲内存

---------------------Heap(运行时堆)--------------通过brk/sbrk系统调用扩大堆,向上增长。

---------------------.data、.bss(读写段)---------从可执行文件中加载

>=0x08048000---------.init、.text、.rodata-------从可执行文件中加载

< 0x08048000---------保留区域--------------------

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-2.3.5.so

0063e000-0063f000 r-xp 00019000 03:01 718192     /lib/ld-2.3.5.so

0063f000-00640000 rwxp 0001a000 03:01 718192     /lib/ld-2.3.5.so

00642000-00766000 r-xp 00000000 03:01 718193     /lib/libc-2.3.5.so

00766000-00768000 r-xp 00124000 03:01 718193     /lib/libc-2.3.5.so

00768000-0076a000 rwxp 00126000 03:01 718193     /lib/libc-2.3.5.so

0076a000-0076c000 rwxp 0076a000 00:00 0

08048000-08049000 r-xp 00000000 03:01 1307138    /root/test/mem/t.exe

08049000-0804a000 rw-p 00000000 03:01 1307138    /root/test/mem/t.exe

09f5d000-09f7e000 rw-p 09f5d000 00:00 0          [heap]

57e2f000-b7f35000 rw-p 57e2f000 00:00 0

b7f44000-b7f45000 rw-p b7f44000 00:00 0

bfb2f000-bfb45000 rw-p bfb2f000 00:00 0          [stack]

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=0xbfd3d35c

(0xb7f2cbb0): first=0xb7f2c454

(0xb7f2cbb0): p0=0x84d52d8 p1=0xb4c27008

(0xb752bbb0): first=0xb752b454

(0xb752bbb0): p0=0x84d56e0 p1=0xb4b26008

(0xb6b2abb0): first=0xb6b2a454

(0xb6b2abb0): p0=0x84d5ae8 p1=0xb4a25008

(0xb6129bb0): first=0xb6129454

(0xb6129bb0): p0=0x84d5ef0 p1=0xb4924008

(0xb5728bb0): first=0xb5728454

(0xb5728bb0): p0=0x84d62f8 p1=0xb7e2c008

我们看一下:

主线程与第一个线程的栈之间的距离:0xbfd3d35c - 0xb7f2c454=0x7e10f08=126M

第一个线程与第二个线程的栈之间的距离:0xb7f2c454 - 0xb752b454=0xa01000=10M

其它几个线程的栈之间距离均为10M。

也就是说,主线程的栈空间最大为126M,而普通线程的栈空间仅为10M,超这个范围就会造成栈溢出。

栈溢出的后果是比较严重的,或者出现Segmentation fault错误,或者出现莫名其妙的错误。

Linux的Application 内存模型---的更多相关文章

  1. Linux和进程内存模型

    一.Linux和进程内存模型 jvm是一个进程的身份运行在linux系统上,了解linux和进程的内存关系,是理解jvm和Linux内存关系的基础. 硬件.系统.进程三个层面的内存之间的概要关系 1. ...

  2. 探索 Linux 内存模型--转

    引用:http://www.ibm.com/developerworks/cn/linux/l-memmod/index.html 理解 Linux 使用的内存模型是从更大程度上掌握 Linux 设计 ...

  3. 【原创】(四)Linux内存模型之Sparse Memory Model

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  4. 深入理解java虚拟机(linux与jvm内存关系)

    本文转载自美团技术团队发表的同名文章 https://tech.meituan.com/linux-jvm-memory.html 一, linux与进程内存模型 要理解jvm最重要的一点是要知道jv ...

  5. Linux内存模型

    http://blog.csdn.net/sunyubo458/article/details/6090946 了解linux的内存模型,或许不能让你大幅度提高编程能力,但是作为一个基本知识点应该熟悉 ...

  6. 【转】浅析linux内存模型

    转自:http://pengpeng.iteye.com/blog/875521 0. 内存基本知识 我们通常称 linux的内存子系统为:虚拟内存子系统(virtual memory system) ...

  7. 从linux进程角度看JVM内存模型

    普通进程栈区,在JVM一般仅仅用做线程栈,如下图所示 首先是永久代.永久代本质上是Java程序的代码区和数据区.Java程序中类(class),会被加载到整个区域的不同数据结构中去,包括常量池.域.方 ...

  8. 【深入理解计算机系统02】ISA 与内存模型

    第二篇:认识ISA(Instruction Set Architecture) 重要概念: [ISA] [IA-32]:Intel把32位x86架构的名称x86-32改称为IA-32,一种身边很常见的 ...

  9. java内存模型及分块

    转自:http://www.cnblogs.com/BangQ/p/4045954.html 1.JMM简介 2.堆和栈 3.本机内存 4.防止内存泄漏   1.JMM简介   i.内存模型概述 Ja ...

随机推荐

  1. 【SVN】自动定时更新

    程序或脚本:"C:\Program Files\TortoiseSVN\bin\svn.exe" 参数:update E:\XXXXProjects\Code 参考:https:/ ...

  2. linux-满足多字符条件统计行数

    测试数据: 2017-10-24 14:14:11:1123 [ INFO] order_type=add,order_id=9150882564978710367790292017-10-24 14 ...

  3. PHP代码审计笔记--任意文件上传

     0x01 最简单的文件上传 未进行文件类型和格式做合法性校验,任意文件上传 漏洞代码示例: 新建一个提供上传文件的 upload.html <html> <body> < ...

  4. PHP代码审计笔记--CSRF漏洞

    0x01 前言 CSRF(Cross-site request forgery)跨站请求伪造.攻击者盗用了你的身份,以你的名义向第三方网站发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻 ...

  5. radio的取值

    <dd id="pingjia${evaluation.orderItemId }" class="ms-wf clearfix" idx="$ ...

  6. javaweb项目中表单生成的验证码以及校验

    首先先来看一下项目的结构吧,有两个servlet,一个是进行验证码的生成以及存储的,一个是进行校验的,还有一个jsp页面是用来实现form表单的书写和展示: 我们只需要看这三个就行了,其他的自动忽略: ...

  7. PON系统基础知识简介

    一  PON基础知识 1.1 PON技术概念 PON(Passive Optical Network)即无源光网络,一种基于点到多点(P2MP)拓朴的技术.“无源”指ODN(光分配网络)不含有任何电子 ...

  8. 【Spring源码深度解析学习系列】Bean的加载(六)

    Bean的加载所涉及到的大致步骤: 1)转换对应beanName 为什么需要转换beanName呢?因为传入的参数可能是别名,也可能是FactoryBean,所以需要一系列的解析,这些解析内容包括如下 ...

  9. Free Download Manager (FDM) 中文版 - 替代迅雷最佳免费开源下载工具软件

    https://www.freedownloadmanager.org/ Free Download Manager (FDM) 是一款经典免费纯粹的下载软件,它开源无广告,界面简洁清爽,支持 BT. ...

  10. c实现的list

    // clist.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"#include <stdio.h>#include <ma ...