《Linux内核设计与实现》读书笔记之进程地址空间

1.进程的内核区域包含各种内存对象

进程的内核区域包含各种内存对象,比如:

1.可执行文件代码可以包含各种内存映射,称为代码段(text section)。

2.可执行文件的已初始化全局变量的内存映射,称为数据段(data section)。

3.包含未初始化全局变量,也就是bss段的零页(页面中的信息全部为0值,所以可以用于映射bss段等目的)的内存映射。

4.用于进程用户空间栈的内存映射。

5.每一个诸如c库或动态链接程序等共享库的代码段、数据段和bss段也会被载入进程的地址空间。

6.任何内存映射文件。

7.任何共享内存段

8.任何匿名的内存映射,比如由malloc()分配的内存。

2.内存描述符

内核使用内存描述符结构体表示进程的地址空间,该结构体包含了和进程地址空间有关的全部信息。内存描述符由mm_struct结构体表示,它的定义为:

mm_user域记录正在使用该地址的进程数目。mmap和mm_rb这两个不同数据结构体描述的对象是相同的:该地址空间中的全部内存区域。但是前者以链表的方式存放而后者以红黑树的结构存放。内核通常会避免使用两种数据结构组织同一种数据,但此时内核这样的冗余完全派的上用场。mmap作为链表,利于简单、高效地遍历所有元素;而mm_rb则更合适搜索指定的元素。

所有的mm_struct结构体都通过自身的mmlist域链接在一个双向链表中,该链表的首元素是init_mm内存描述符,它代表init进程的地址空间,在操作该链表的时候需要使用mmlist_lock锁来防止并发访问。

3.内存区域

内存区域由vm_area_struct结构体描述,它的定义如下:

每个内存描述符都对应于进程地址空间中的唯一区间。vm_start域指向区间的首地址,vm_end域指向区间的尾地址。需要注意的是,在同一个地址空间内的不同内存区间不能重叠。

vm_mm域指向和VMA相关的mm_struct结构体,注意每个VMA对其相关的mm_struct结构体来说都是唯一的,所以即使两个独立的进程将同一个文件映射到各自的地址空间,它们分别都会有一个vm_area_struct结构体来标志自己的内存区域;但是如果两个线程共享同一个地址空间,那么它们也同时共享其中的所有vm_area_struct结构体。

4.VMA标志

VMA标志是一种位标志,它包含在vm_flags域内,标志了内存区域所包含的页面的行为和信息。当访问VMA时,需要查看其访问权限。VMA的可选标志如下所示:

5.实际举例

我们用一个非常简单的用户控件程序的例子,它其实什么也不做,仅仅是为了做说明用:

int main(int argc,char * argv[])

{

return 0;

}

下面列出该进程地址空间中包含的内存区域。其中有代码段、数据段、和bss段等。该进程与C库动态链接,那么地址空间中还将分别包含libc.so和ld.so对应的上述三种内存区域。此外,地址空间中还要包含进程栈对应的内存区域。

前三行分别对应C库中libc.so的代码段、数据段、和bss段,接下来三行是动态链接程序ld.so的代码段、数据段、和bss段,最后一行是进程的栈。

该进程的全部地址空间大约1340KB,但是只有约40KB的内存区域是可写和私有的。如果一片内存范围是共享的或不可写的,那么内核只需要在内存为文件保留一份映射多以C库在无力内存中仅仅需要占用1212KB的空间,而不需要为每个使用C库的进程在内存中都保存一个1212KB的空间。进程访问了1340KB的数据和代码空间,然而仅仅消耗了40KB的物理内存,可以看出利用这种共享不可写内存的方法节约了大量的内存。

注意没有映射文件的内存区域的设备标志位00:00,索引节点标志也为0,这个区域就是零页。如果将零页映射到可写的内存区域,那么该区域将被初始化为全0。这是零页的一个重要的用处,而bss段需要的就是全0的内存区域。由于内存未被共享,所以只要一有进程写该数据,那么该数据就将被拷贝出来(就是我们说的写时拷贝),然后才被更新。

6.动态链接的过程举例(参考《CSAPP》)

动态链接的过程如下所示:

在创建可执行文件p2时,没有任何libvector.so的代码和数据节真的被拷贝到可执行文件p2中,链接器只拷贝了一些重定位和符号表信息,它们使得运行时可以解析对libvector.so中代码和数据的引用。

当加载器加载和运行可执行文件时,它注意到可执行文件有一个.interp节,这个节包含动态链接器的路径名,动态链接器本身就是一个共享目标,加载器不再像它通常那样将控制传递给可执行程序,而是加载和运行这个动态链接器。然后,动态链接器通过执行下面的重定位完成链接任务:

·重定位libc.so的文本和数据到某个存储器段。

·重定位libvector.so的文本和数据到另一个存储器段。

·重定位p2中所有由libc.so和libvector.so定义的符号引用。

最后,动态链接器将控制全转移给应用。

时间: 2024-11-08 20:03:27

《Linux内核设计与实现》读书笔记之进程地址空间的相关文章

Linux内核设计与实现 读书笔记 转

Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://blog.csdn.net/yrj/article/category/718110 Linux内存管理和性能学习笔记(一) :内存测量与堆内存 第一篇 内存的测量 2.1. 系统当前可用内存 # cat /proc/meminfoMemTotal:        8063544 kBMemFree:       

Linux内核设计与实现读书笔记——第三章

Linux内核设计与实现读书笔记——第三章 进程管理 20135111李光豫 3.1进程 1.进程即处于执行期的程序,并不局限于一个可执行的代码,是处于执行期程序以及其相关资源的总称. 2.Linux系统中,对于进程和线程并没有明显的区分,线程是一种特殊的进程. 3.Linux系统中,常用fork()进程创建子进程.调用fork()进程的成之为其子进程的父进程. 4.fork()继承实际上由clone()系统调用实现.最后通过exit()退出执行. 3.2任务描述符及任务结构 1.任务队列实质上

Linux内核设计与实现 读书笔记

第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的task_struct连在一起组成了一个双向链表 3. 2.6内核的内核栈底放的是thread_info结构,其中有指向task_struct的指针: 4. current宏可以找到当前进程的task_struct:X86是通过先找到thread_info结构,而PPC是有专门的寄存器存当前task_s

Linux内核设计与实现读书笔记——第十八章

第18章 调试 调试工作艰难是内核级开发区别于用户级开发的一个显著特点,相比于用户级开发,内核调试的难度确实要艰苦得多.更可怕的是,它带来的风险比用户级别更高,内核的一个错误往往立刻就能让系统崩溃. 18.1 准备开始 一个bug.听起来很可笑,但确实需要一个确定的bug.如果错误总是能够重现的话,那对我们会有很大的帮助(有一部分错误确实如此).然而不幸的是,大部分bug通常都不是行为可靠而且定义明确的. 一个藏匿bug的内核版本.如果你知道这个bug最早出现在哪个内核版本中那就再理想不过了.

《Linux内核设计与实现读书笔记之系统调用》

1.系统调用的概念 为了和用户空间上运行的进程进行交互,内核提供了一组借口.透过该接口,应用程序可以访问硬件设备和其他操作系统资源.这组借口在应用程序和内核之间扮演着使者的角色.同时,这组接口也保证了系统稳定可靠,避免应用程序肆意妄行,惹出麻烦.Linux系统的系统调用作为C库的一部分提供,其调用过程中的实例如下图所示: 从程序员的角度看,系统调用无关紧要,他们只需要跟API打交道就可以了.相反,内核只跟系统调用打交道,库函数以及应用程序是怎么使用系统调用不是内核所关心的. 2.系统调用的处理程

Linux内核设计与实现——读书笔记2:进程管理

1.进程: (1)处于执行期的程序,但不止是代码,还包括各种程序运行时所需的资源,实际上进程是正在执行的 程序的实时结果. (2)程序的本身并不是进程,进程是处于执行期的程序及其相关资源的总称. (3)两个或两个以上并存的进程可以共享诸如打开的文件,地址空间等共享资源. (4)在Linux中通常是调用fork()系统函数的结果,通过复制一个现有的进程来创建一个新的子进程. fork()系统函数 (5)fork在这个系统调用结束时,在同一位置上返回两次(从内核返回两次),父进程恢复运行,子进程开始

《Linux内核设计与实现》笔记-1-linux内核简介

一.Linux内核相对于传统的UNIX内核的比较: (1):Linux支持动态内核模块.尽管Linux内核也是整体式结构,可是允许在需要的时候动态哦卸除(rmmod xxx)和加载内核模块(insmod  xxx.ko). (2):Linux支持对称多处理(SMP)机制,尽管许多UNIX的变体也支持SMP,但是传统的UNIX并不支持这种机制. (3):Linux内核可以抢占(preemptive).在Linux 2.4以及以前的版本都是不支持内核抢占的,在Linux 2.6以及以后就支持了. (

《Linux内核设计与实现》笔记——内核同步简介

相关概念 竞争条件 多个执行线程(进程/线程/中断处理程序)并发(并行)访问共享资源,因为执行顺序不一样造成结果不一样的情况,称为竞争条件(race condition) 举例说明 #include<thread> using namespace std; int i = 0; void thread1(){ //for(int x=0;x<100000;x++) i++; } void thread2(){ //for(int x=0;x<100000;x++) i++; } i

Linux内核架构与底层--读书笔记

linux中管道符"|"的作用 命令格式:命令A|命令B,即命令1的正确输出作为命令B的操作对象(下图应用别人的图片) 1. 例如: ps aux | grep "test"  在 ps aux中的結果中查找test. 2. 例如:   find . -name "*.txt" | xargs grep "good" -n --color=auto   把find的结果当成参数传入到grep中,即在那些文件内部查找good关键