读书笔记之linux内核设计与实现(13)进程地址空间
内核除了管理本身的内存外,还必须管理进程的地址空间——也就是系统中每个用户空间进程所看到的内存。Linux操作系统采用虚拟内存技术,因此,系统中的所有进程之间以虚拟方式共享内存。对每个进程来说,它们好像都可以访问整个系统的所有物理内存。更重要的是,即使单独一个进程,它拥有的地址空间也可以远远大于系统物理内存。
进程地址空间由每个进程中的线性地址区组成,而且更为重要的特点是内核允许进程使用该空间中的地址。每个进程都有一个32位的平坦(flat)地址空间。“平坦”描述的地址空间范围是一个独立的连续区间。通常情况下,每个进程都有唯一的这种平坦地址空间,而且进程地址空间之间彼此互不相干。两个不同的进程可以在他们各自地址空间的相同地址内存存放不同的数据。但是进程之间也可以选择共享地址空间,我们称这样的进程为线程。 在地址空间中,我们往往更为关心的是进程有权访问的虚拟内存地址空间,比如08048000-0804c000。这些可被访问的合法地址区间被称为内存区域(memory area),通过内核,进程可以给自己的地址空间动态的添加或减少内存区域。 进程只能访问有效范围内的内存地址。每个内存区域也具有相应进程必须遵循的特定访问属性,如只读、只写、可执行等属性。
内存区域可以包含各种内存对象:
可执行文件代码的内存映射,成为代码段(text section)。
可执行文件的已初始化全局变量的内存映射,称为数据段(data section)。
包含未初始化全局变量,也就是bss段的零页的内存映射。
用于进程用户空间栈(不要和进程内核栈混淆,进程的内核栈独立存在并由内核维护)的零页的内存映射。
每一个诸如C库或动态连接程序等共享库的代码段、数据段和bss也会被载入进程的地址空间。
任何内存映射文件。
任何共享内存段。
任何匿名的内存映射,比如由malloc()分配的内存。
14.1 内存描述符
内核使用内存描述符结构体表示进程的地址空间,该结构体包含了和进程地址空间有关的全部信息。内存描述符由mm_struct结构体表示,定义在<linux/sched.h>中。
mm_users域记录正在使用该地址的进程数目。mm_count域是mm_struct结构体的主引用计数。只要前者不为0,那么后者为1。当mm_count的值为0时,说明已经没有任何指向该mm_struct结构体的引用了,这时该结构体会被销毁。mmap和mm_rb这两个不同的数据结构描述的对象是相同的:该地址空间中的全部内存区域。所有的mm_struct结构体都通过自身的mmlist域连接在一个双向链表中,该链表的首元素是init_mm内存描述符,它代表了init进程的地址空间。
14.1.1 分配内存描述符
在进程的进程描述符中,mm域存放着该进程使用的内存描述符,所以current->mm便指向当前进程中的内存描述符。fork()函数利用copy_mm()函数复制父进程的内存描述符,也就是current->mm域给其子进程,而子进程中的mm_struct结构体实际上是通过文件kernel/fork.c中的allocate_mm()宏从mm_cachep slab缓存中分配得到的。通常每个进程都有唯一的mm_struct结构体,即唯一的进程地址空间。
如果父进程希望和其子进程共享地址空间,可以在调用clone()时,设置CLONE_VM标志。我们把这样的进程叫做线程。
14.2 内存区域
我们先来看一下内存区域和线程地址空间的关系,前面提到,每个进程都有一个32位
你可能喜欢
- 管理机制
- 编程指南
- 虚拟地址
- 虚拟空间
- linux内核启动分析
- 环境卫生管理机制2页
- 计算机硬件设备故障管理机制研究82页
- 01-财务管理机制41页
- 管理机制8页
- 优化 机电设备管理机制7页
- 管理机制88页
- c语言SOCKET编程指南63页
- 338手台编程指南1页
- 手机、PDA编程指南6页
- MetaTrader Version4编程指南21页
- 多线程编程指南(二)5页
- php5高级编程指南2页


