linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】

转自:http://blog.csdn.net/gongweijiao/article/details/8207333

原文参见:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201215115845553/ 

 

一)概述

  .堆栈是一个用户空间的内存区域,进程使用堆栈作为临时存储

 

  .堆栈中存放的是函数中的局部变量,在函数的生命周期中可以将变量压入堆栈,编译器需要确保堆栈指针在函数退出前恢复到初始位置,也就是说,内存是自动分配和释放的,C/C++存储在堆栈中的局部变量当作automatic存储,并使用auto关键字,这是局部变量的默认存储方式,所以现在没有人用auto关键词.

 

  .与动态存储(auto)相对映的静态存储(static),也就是用static定义的局部变量,它不用堆栈来存储,而是使用数据段来存储(也就是说它的生命周期在整个程序运行期间)。

 

  .堆栈的基地址位于用户空间的最高虚拟地址附近,并从那里向下延伸。

  .一个进程开始时,堆栈的最大值就不能改变,如果占用的空间超过了堆栈大小,那么就会导致堆栈溢出。

二)进程的内存组织形式

  进程被分为三个区域:文本数据堆栈

  1)文本区域:

   文本区域也叫做代码段,是由程序确定的,

它包括代码(指令)和只读数据,该区域通常被标记为只读,任何对其写入的操作会导致段错误.

  2)数据区域(静态内存分配(static)):

  数据区域也叫做数据段,

它包括已初始化和未初始化的数据,静态变量存储在这个区域中,它的大小可以用系统调用brk(2)来改变。

详细了解数据区域:

分成初始化为非零的数据区BSS(Heap)三个区域。

初始化非零数据区域一般存放静态非零数据和全局的非零数据,属于静态内存分配(全局变量,static修饰的变量);

BSS(Block Started by Symbol)区域(都初始化为0了)一般存放未初始化的全局数据(默认值为0)和未初始化的静态数据(默认值为0),属于静态内存分配(全局变量、static修饰的变量);

堆区域一般存放运行时动态分配的内存空间,其大小不固定,可动态扩张或缩减。当调用malloc等函数分配内存时,新分配的内存被动态添加到堆上;当调用free等函数释放内存时,被释放内存从堆中被剔除。

代码段和数据段之间有明确的分隔,

但是数据段和堆栈段之间没有,而且栈是向下增长,堆是向上增长的,因此理论上堆和栈会“增长到一起”,操作系统的内存管理功能需要防止这样的错误发生。

  3)堆栈区域(动态内存分配auto,默认,所以不用关键字auto):

  堆栈区域也叫堆栈段,

它用于给局部变量动态分配空间,同样函数传递参数和函数返回值也要用到堆栈.

   堆栈也可向下增长(向内存低地址)也可以向上增长,这依赖于具体的实现,

通常都是向下增长的,而SP(堆栈指针)也是指向堆栈的最后地址.

  4)内存的分配区域:

   根据前面所述,堆栈是位于最高虚拟地址附近,而数据段则位于堆栈段之后,最后是代码段。

也就是:

低地址 代码段 或 高地址 堆栈段

数据段 数据段

高地址 堆栈段 低地址 代码段

三)堆栈着色

  当两个线程或进程使用相同的堆栈虚拟地址时,它们会争夺同一个cache行,导致竞争和降级行为.

  堆栈着色的技术使每一个进程的基址都不相同,通过随机分配堆栈基址,多个进程会使用不同的cache行来避免.

四)堆栈的限制

  堆栈空间的最大值是由setrlimit系统调用确定的,也可以通过bash内建的ulimit命令来设定和查看.

  例如:

  查看当前可使用的最大堆栈(以KB为单位)

  ulimit -s

  8192 //栈的大小默认是8M

  设定为最大的使用堆栈为15KB

  ulimit -s 15

  此时执行ls将会得到一个段错误.

  ls -l /etc/

  total 1040

  Segmentation fault

  通过用strace跟踪ls命令,将发现有如下的系统调用

  getrlimit(RLIMIT_STACK, {rlim_cur=15*1024, rlim_max=15*1024}) = 0

  说明当前可用的堆栈空间,已经不足以运行strace命令了.

五)常驻内存和锁定内存

  常驻内存专指存储在RAM中的内存部分,不包括存储在交换区和未存储的进程的内存.

  锁定内存是常驻内存的子集,它指被进程明确地锁定到RAM的虚拟内存中,不能用于交换,并一直常驻于RAM中.

时间: 2024-10-26 15:59:30

linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】的相关文章

java-关于静态变量的一段代码

问题描述 关于静态变量的一段代码 package test; public class Circle2 { double radius; static int number0 = 0; Circle2(){ radius = 1.0; number0++; } Circle2(double newRad){ radius = newRad; number0++; } static int getN(){ return number0; } double getArea(){ return rad

有关进程空间,全局变量,静态变量

[创新性声明]本文没有本质上的创新性内容.属于一些实验和总结,有少量主观推测成分(有待进一步证实).写这一类文章是非常危险的,因为有很多东西可能是我们不了解和比较模糊的,这很可能会出现错误的主观臆测,不仅仅是令明真相者贻笑大方的问题,更可怕的在于传播"错误",这是我最为诚惶诚恐的一点.比如,我之前见到我指点过他的sun先生对于Photoshop中置换滤镜中的他的那些主观错误结论已经传遍网络,尽管可能没有太多人能关注到这个层面,但是我还是为这些错误的观点在网络上比比皆是而深感遗憾.正因为

无需Ptrace就能实现Linux进程间代码注入

本文讲的是无需Ptrace就能实现Linux进程间代码注入, ptrace系统调用 ptrace系统调从名字上看是用于进程跟踪的,它提供了父进程可以观察和控制其子进程执行的能力,并允许父进程检查和替换子进程的内核镜像(包括寄存器)的值.其基本原理是: 当使用了ptrace跟踪后,所有发送给被跟踪的子进程的信号(除了SIGKILL),都会被转发给父进程,而子进程则会被阻塞,这时子进程的状态就会被系统标注为TASK_TRACED.而父进程收到信号后,就可以对停止下来的子进程进行检查和修改,然后让子进

Linux进程和线程的基础与管理

  一.进程的基本概念 程序是为了完成某种任务而设计的软件,比如vi是程序.什么是进程呢? 进程就是运行中的程序.一个运行着程序,可能有多个进程.比如Web服务器是Apache服务器,当管理员启动服务后,可能会有好多人来访问,也就是说许多用户同时请求httpd,Apache服务器将会创建多个httpd进程来对其进行服务. 首先我们看看进程的定义.进程是一个具有独立功能的程序关于某个数据集合的一次可以并发执行的运行活动,是处于活动状态的计算机程序.进程作为构成系统的基本细胞,不仅是系统内部独立运行

Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)

进程状态 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ 1 1 state成员的可能取值如下 参见http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.5#L207 /* * Task state bitmask. NOTE! These bits are also * encoded in fs/proc/array.c: get_task

LINUX(十二) Linux进程查看

   本节中要介绍的不只是进程查看方面的内容,由于Linux是个多用户系统,有时候也要了解其他用户现在在干什么,所以在本节中还将接触多用户方面的内容.同时Linux是一个多进程系统,经常需要对这些进程进行一些调配和管理:而要进行管理,首先就要知道现在的进程情况:究竟有哪些进程?进程情况如何?等等.所以需要进程查看方面的工作. who命令 该命令主要用于查看当前在线上的用户情况.这个命令非常有用.如果用户想和其他用户建立即时通讯,比如使用talk命令,那么首先要确定的就是该用户确实在线上,不然ta

Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)【转】

转自:http://blog.csdn.net/gatieme/article/details/51872659 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme   目录(?)[-] 前景回顾 1 Linux的调度器组成 2 调度工作 进程上下文 1 进程上下文的概念 2 上下文切换 context_switch进程上下文切换 1 context_switch完全注释 2 prepare_arch_switch切换前的准备工

Linux进程管理——fork()和写时复制

写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork(  )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要:   ·      为子进程的页表分配页面 ·      为子进程的页分配页面 ·      初始化子进程的页表 ·      把父进程的页复制到子进程相应的页中   创建一个地址空间的这种方法涉及许多内存访问,消耗许多CPU周期,并且完全破坏了高速缓存中的内容.在大多数情况下,这样做常常是毫无意义的,

Linux进程通信(IPC)方式简介

linux下进程间通信的几种主要方式:管道(pipe)和有名管道(FIFO).信号(signal).消息队列.共享内存(shared memory).信号量(semaphore).套接字(socket),本文对这些做简单介绍 进程间通信的目的 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间. 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(