Linux C进程内存布局

当程序文件运行为进程时,进程在内存中获得空间。这个空间是进程自己的内存空间。每个进程空间按照如下方式分为不同区域:

            

                                进程内存空间布局图

text:代码段。存放的是程序的全部代码(指令),来源于二进制可执行文件中的代码部分

initialized data(简称data段)和uninitialized data(简称bss段)组成了数据段。其中data段存放的是已初始化全局变量和已初始化static局部变量,来源于二进制可执行文件中的数据部分;

bss段存放的是未初始化全局变量和未初始化static局部变量,其内容不来源于二进制可执行文件中的数据部分(也就是说:二进制可执行文件中的数据部分没有未初始化全局变量和未初始化static局部变量)。根据C语言标准规定,他们的初始值必须为0,因此bss段存放的是全0。将bss段清0的工作是由系统在加载二进制文件后,开始执行程序前完成的,系统执行这个清0操作是由内核的一段代码完成的,这段代码就是exec系统调用。

stack(栈)存放的是动态局部变量。也就是说,当子函数被调用时,系统会从栈中分配空间给该子函数的动态局部变量(注意:此时栈向内存低地址延伸);当子函数返回时,系统的栈会向内存高地址延伸,这相当于释放子函数的动态局部变量的内存空间。

在进程运行的过程中,通过调用和返回函数,控制权不断在函数间转移。进程可以在调用函数的时候,原函数的帧中保存有在我们离开时的状态,并为新的函数开辟所需的帧空间。在调用函数返回时,该函数的帧所占据的空间随着帧的弹出而清空。进程再次回到原函数的帧中保存的状态,并根据返回地址所指向的指令继续执行。上面过程不断继续,栈不断增长或减小,直到main()返回的时候,栈完全清空,进程结束。

当程序中使用malloc的时候,堆(heap)会向上增长,其增长的部分就成为malloc从内存中分配的空间。malloc开辟的空间会一直存在,直到我们用free系统调用来释放,或者进程结束。一个经典的错误是内存泄漏(memory leakage), 就是指我们没有释放不再使用的堆空间,导致堆不断增长,而内存可用空间不断减少。

栈和堆的大小则会随着进程的运行增大或者变小。当栈和堆增长到两者相遇时候,也就是内存空间图中的unused area区域完全消失的时候,再无可用内存。进程会出现栈溢出(stack overflow)的错误,导致进程终止。在现代计算机中,内核一般会为进程分配足够多unused area区域,如果清理及时,栈溢出很容易避免。即便如此,内存负荷过大,依然可能出现栈溢出的情况。我们就需要增加物理内存了。

内存的最高端存放的是命令行参数和环境变量,将命令行参数和环境变量放到指定位置这个操作是由OS的一段代码(exec系统调用)在加载二进制文件到内存后,开始运行程序前完成的。

                

Linux C进程内存布局,布布扣,bubuko.com

时间: 2024-11-05 18:40:27

Linux C进程内存布局的相关文章

linux下进程内存布局及变量存储位置检查

进程的内存布局如下(虚拟内存): 它们分别从低地址向高地址增长 在linux中,存在三个全局符号:etext, edata, end分别指向文本段,初始化数据段,未初始化数据段结尾处的下一字节的地址. 所以我们可以在c程序中声明这些变量,然后定义一些变量再查看其地址是否在对应的地址范围内,可得出其变量被存储在哪个区中. #include<unistd.h> #include<stdlib.h> #include<stdio.h> extern char etext, e

一个由进程内存布局异常引起的问题

一个由进程内存布局异常引起的问题 前段时间业务反映某类服务器上更新了 bash 之后,ssh 连上去偶发登陆失败,客户端吐出错误信息如下所示:图 - 0 该版本 bash 为部门这边所定制,但实现上并没有改动原有逻辑,只是加入了些监控功能,那么这些错误从哪里来呢? 是 bash 的锅吗 从上面的错误信息可以猜测,异常是 bash 在启动过程中分配内存失败所导致,看起来像是某些情况下该进程错误地进行了大量内存分配,最后导致内存不足,要确认这个事情比较简单,动态内存分配到系统调用这一层上主要就两种方

Linux x86_64进程内存空间布局

关于Linux 32位内存下的内存空间布局,可以参考这篇博文Linux下C程序进程地址空间局关于源代码中各种数据类型/代码在elf格式文件以及进程空间中所处的段,在x86_64下和i386下是类似的,本文主要关注vm.legacy_va_layout以及kernel.randomize_va_space参数影响下的进程空间内存宏观布局. 情形一: vm_legacy_va_layout=1 kernel.randomize_va_space=0 此种情况下采用传统内存布局方式,不开启随机化 ca

linux系统进程的内存布局

内存管理模块是操作系统的心脏:它对应用程序和系统管理非常重要.今后的几篇文章中,我将着眼于实际的内存问题,但也不避讳其中的技术内幕.由于不少概念是通用的,所以文中大部分例子取自32位x86平台的Linux和Windows系统.本系列第一篇文章讲述应用程序的内存布局. 在多任务操作系统中的每一个进程都运行在一个属于它自己的内存沙盘中.这个沙盘就是虚拟地址空间(virtual address space),在32位模式下它总是一个4GB的内存地址块.这些虚拟地址通过页表(page table)映射到

Linux查看进程内存占用及内存使用情况

LINUX进程内存占用查看方法(1)top可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看,如想查看oracle用户的进程内存使用情况的话可以使用如下的命令:$ top -u oracle (2)pmap可以根据进程查看进程相关信息占用的内存情况,(进程号可以通过ps查看)如下所示:$ pmap -d 14596 (3)ps如下例所示:$ ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' 其中rsz是是实际内存

linux进程内存布局

一个程序本质上都是由 BSS 段.data段.text段三个组成的.这样的概念在当前的计算机程序设计中是很重要的一个基本概念,而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配,存储单元占用空间大小的问题. BSS段:在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段:在采用段式内存管理的架构中,数据段(da

Unix系统编程()进程内存布局

每个进程所分配的内存由很多部分组成,通常称之为"段(segment)". 文本段包含了进程运行的程序机器语言指令.文本段具有只读属性,以防止进程通过错误指针意外修改自身指令. 因为多个进程可同时运行同一程序,所以又将文本段设为可共享,这样,一份程序代码的拷贝可以映射到所有这些进程的虚拟地址空间中. 初始化数据段包含显式初始化的全局变量和静态变量.当程序加载到内存时,从可执行文件中读取这些变量的值. 未初始化数据段包括了未进行显式初始化的全局变量和静态变量. 程序启动之前,系统将本段内所

c进程内存布局说明

Text:代码段.存放程序的全部代码(指令),来源于二进制可执行文件中的代码部分,在编译的时候就已经放置到二进制文件中. Initialized data(简称data段)和uninitialized data(简称bss段)组成了数据段.其中data段存放的是已初始化全局变量和已初始化static局部变量,来源于二进制可执行文件中的数据部分,这部分在编译的时候就已经放置到二进制文件中:bss段存放的是未初始化全局变量和未初始化static局部变量,其内容不来源于二进制可执行文件中的数据部分(也

进程内存和内存损坏

本教程的这一部分的先决条件是对ARM汇编的基本了解(在第一个教程系列" ARM汇编基础 "中有介绍).在本章中,您将了解32位Linux环境中进程的内存布局.之后,您将学习堆栈和堆相关的内存损坏的基本原理,以及它们在调试器中的样子. 缓冲区溢出 堆栈溢出 堆溢出 摇摇欲坠的指针 格式字符串 本教程中使用的示例是在ARMv6 32位处理器上编译的.如果您无法访问ARM设备,则可以按照以下教程创建自己的实验室并在VM中模拟Raspberry Pi发行版:使用QEMU模拟Raspberry