Linux进程地址空间和虚拟内存

一、虚拟内存

先来看一张图(来自《Linux内核完全剖析》),如下:

分段机制:即分成代码段,数据段,堆栈段。每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低特权级(用户),每当程序试图访问(权限又分为可读、可写和可执行)一个段时,当前特权级CPL就会与段的特权级进行比较,以确定是否有权限访问。每个特权级都有自己的程序栈,当程序从一个特权级切换到另一个特权级上执行时,堆栈段也随之改换到新级别的堆栈中。

段选择符:每个段都有一个段选择符。段描述符指明段的大小、访问权限和段的特权级、段类型以及段的第一个字节在线性地址空间中的位置(称为段的基地址)。而段选择符用于在描述符表中进行索引找到段描述符。

虚拟地址:虚拟地址的偏移量部分加上段的基地址上就可以定位段中某个字节的位置,即形成线性地址空间中的地址。

分页机制:当使用分页机制时,每个段被划分成页面(通常每页在4KB大小),页面会被存储于物理内存或硬盘上。如果禁用分页机制,那么线性地址空间就是物理地址空间。

当程序试图访问线性地址空间上的一个地址位置时,发生以下操作:

C++ Code


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 
if(数据在物理内存中)

{

虚拟地址转换成物理地址

读数据

}

else

{

if(数据在磁盘中)

{

if(物理内存还有空闲)

{

把数据从磁盘中读到物理内存

虚拟地址转换成物理地址

读数据

}

else

{

把物理内存中某页的数据存入磁盘

把要读的数据从磁盘读到该页的物理内存中

虚拟地址转换成物理地址

读数据

}

}

else

{

报错

}

}

其中MMU负责虚拟地址到物理地址的转换工作,分段和分页操作都使用驻留在内存中的段表和页表来指定他们各自的交换信息。如果用户程序想要访问一个虚拟地址,经MMU检查无权访问(特权级),MMU产生一个异常,CPU从用户模式切换到特权模式,跳转到内核代码中执行异常服务程序,内核把这个异常解释为段错误,把引发异常的进程终止掉。

二、linux进程地址空间

由前面可得知,进程有4G的寻址空间,其中第一部分为“用户空间”,用来映射其整个进程空间(0x0000 0000-0xBFFF FFFF)即3G字节的虚拟地址;第二部分为“系统空间”,用来映射(0xC000 0000-0xFFFF FFFF)1G字节的虚拟地址。如下图

将其更加详细地展示如下:

程序路径:完整的绝对路径字符串如 “/home/simba/code/asm/simple”

环境变量:类似linux下的PATH,HOME等的环境变量,子进程会继承父进程的环境变量。

命令行参数:类似ls -l 中-l 就是命令行参数,而ls 就是可执行程序。

栈:就是堆栈,程序运行时需要在这里做数据运算,存储临时数据,开辟函数栈等。在Linux下,栈是高地址往低地址增长的。

对于函数栈来说,函数运行完毕就释放内存,举例递归来说,一直开辟向下函数栈,然后由下往上收复,所以递归太多层的话很可能造成栈溢出。

局部变量(不包含静态变量);局部可读变量(const)都分配在栈上。

共享库和mmap内存映射区:比如很多程序都会用到的printf,函数共享库 printf.o 固定在某个物理内存位置上,让许多进程映射共享。mmap是个系统函数,可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。此外,调用malloc 时正常是调用brk 系统调用分配内存,特定条件下是调用mmap
来映射物理内存到进程地址空间。

堆:即malloc申请的内存,使用free释放,如果没有主动释放,在进程运行结束时也会被释放。

Text Segment: 可执行程序(二进制)(.text);全局初始化只读变量(const)(.rodata);字符串常量(.rodata);均在这里分配。

Data Segment: 全局变量(初始化的在.data,未初始化的在.bss);静态变量(全局和局部)(初始化的在.data,未初始化的在.bss);全局未初始化只读变量(.bss);均在这里分配。

原文地址:https://www.cnblogs.com/alantu2018/p/8472723.html

时间: 2024-10-10 22:59:37

Linux进程地址空间和虚拟内存的相关文章

Linux进程地址空间与虚拟内存

http://blog.csdn.net/xu3737284/article/details/12710217 32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.进程的地址空间存在于虚拟内存中.虚拟内存不能被禁用. 进程地址空间 进程地址空间分为内核空间和用户空间 因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享.于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间. A.正文段.这是由cpu执行的

Linux进程地址空间的理解

对于Linux的虚拟内存的理解,这个例子算是一个很好的引导了,原文链接:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26683523&id=3201345 <Linux内核设计与实现>15章节给出的例子更详细些. ************************************************************************** 先介绍Linux进程地址空间的数据结构更方便理解,

linux进程地址空间详解(转载)

linux进程地址空间详解(转载) 在前面的<对一个程序在内存中的分析 >中很好的描述了程序在内存中的布局,这里对这个结果做些总结和实验验证.下面以Linux为例(实验结果显示windows上的结果也一样). 我们还是利用前面看到过的这个图,如下图:32位X86机器的内存布局图,内存主要分为栈.堆.BSS段.数据段.代码段5个段.   代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域.这部分区域的大小在程序运行前就已经确定,并且内存

linux进程地址空间--vma的基本操作【转】

转自:http://blog.csdn.net/vanbreaker/article/details/7855007 版权声明:本文为博主原创文章,未经博主允许不得转载. 在32位的系统上,线性地址空间可达到4GB,这4GB一般按照3:1的比例进行分配,也就是说用户进程享有前3GB线性地址空间,而内核独享最后1GB线性地址空间.由于虚拟内存的引入,每个进程都可拥有3GB的虚拟内存,并且用户进程之间的地址空间是互不可见.互不影响的,也就是说即使两个进程对同一个地址进行操作,也不会产生问题.在前面介

linux 进程地址空间的一步步探究

我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间是什么呢,它与实际物理内存空间又是怎样对应的呢,为什么有了虚拟内存技术,我们就能运行比实际物理内存大的应用程序,它是怎么做到的呢?呵呵,这一切的一切都是个迷呀,下面我们就一步一步解开心中的谜团吧! 进程使用虚拟内存中的地址,由操作系统协助相关硬件,把它“转换”成真正的物理地址.虚拟地址通过页表(Pa

Linux进程地址空间的一步步探究

我们知道,在32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G-4G是内核空间.其实,这个4G的地址空间是不存在的,也就是我们所说的虚拟内存空间. 那虚拟内存空间是什么呢,它与实际物理内存空间又是怎样对应的呢,为什么有了虚拟内存技术,我们就能运行比实际物理内存大的应用程序,它是怎么做到的呢? 呵呵,这一切的一切都是个迷呀,下面我们就一步一步解开心中的谜团吧! 我们来看看,当我们写好一个应用程序,编译后它都有什么东东? 例如: 用命令size a.out会得到

[Linux]进程(十)——进程地址空间

1,进程的虚拟内存: 背景知识a.out分段以及运行时候内存的结构点击打开链接 linux进程地址空间 linux进程地址空间 \ [cpp] view plaincopy struct mm_struct { struct vm_area_struct  *mmap;               /* list of memory areas */ struct rb_root         mm_rb;               /* red-black tree of VMAs */

linux进程的地址空间,核心栈,用户栈,内核线程

linux进程的地址空间,核心栈,用户栈,内核线程 地址空间: 32位linux系统上,进程的地址空间为4G,包括1G的内核地址空间,和3G的用户地址空间. 内核栈: 进程控制块task_struct中保存了2个page大小的信息. 为什么每一个进程都是用各自的内核栈呢? 引用(http://hi.baidu.com/iruler/blog/item/0c3363f377ccc5c90a46e023.html)“ 假设某个进程通过系统调用运行在内核态(使用这个全局内核堆栈),此时如果被抢占,发生

把握linux内核设计思想(十三):内存管理之进程地址空间

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet.文章仅供学习交流,请勿用于商业用途] 进程地址空间由进程可寻址的虚拟内存组成,Linux 的虚拟地址空间为0~4G字节(注:本节讲述均以32为为例).Linux内核将这 4G 字节的空间分为两部分.将最高的 1G 字节(从虚拟地址0xC0000000到0xFFFFFFFF).供内核使用,称为"内核空间". 而将较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF),供各个进程使