linux内核几大模块,linux内核完全剖析

1:一个完整的操作系统主要包括四个部分:硬件系统,操作系统内核,操作系统服务和用户应用程序。

2:用户应用程序包括字处理程序,internet浏览器程序,以及用户自己的编写的程序。操作系统的服务程序是指那些为用户提供看作是操作系统部分部分功能的程序。包括X窗口系统,shell命令解释器,以及内核编程的系统程序。

3:操作系统的内核程序主要是对硬件资源的抽象和访问调度。

4:操作系统的结构模式现在为整体的单内核和层次式的微内核。linux即为单内核,优点是结构紧凑,执行速度快,缺点是层次结构不足。

操作系统的所提供的服务是:

应用主程序利用指定的参数执行int80,使CPU从用户态转到内核态,操作系统根据具体的参数值调用相应的服务程序,再根据需要调用相关的底层函数,完成后又回到用户态,继续执行应用程序后面的指令。

总的来说:分为三个层次,相应的主程序层特定参数执行Int80,执行系统调用的服务程序和支持系统调用的的底层函数,最后回到用户态。

主程序

系统服务  系统服务  系统服务...........

支持函数支持函数支持函数支持函数支持函数支持函数

5:

linux内核分为 5个模块:进程调度,内存管理,文件系统模块

,进程间通信,和网络接口模块

进程间调度模块主要是:公平有效地让进程访问cpu,保证内核有效地执行硬件操作。

内存管理模块主要是让各进程共享主存,内存模块也支持虚拟的内存管理模式,使用比实际内存空间更大的内存容量。利用文件系统把暂时不用的数据交换到外存,必要时交换回来。

文件系统模块:用于支持对外部设备的驱动和存储。

虚拟的文件系统通过向所有的外部设备提供一个通用的文件接口,隐藏各种设备的不同细节,支持各种不同的文件格式。

进程间通信支持多种通信方式:

网络接口提供网络通信标准的访问并支持许多网络硬件。

6:一个模块通常在等待硬件时候被挂起,而在硬件正常运行的时候被唤醒。

7:为了合理的使用内存的物理空间,可以将内存的物理空间分为几个部分?

最开始的部分是内核部分,然后就是硬盘软盘等块设备的所使用的缓冲区(缓冲区中还包括640-1M的bios和显卡内存),内存的最后一部分供所有程序包括内核程序在内的程序申请申请和使用的主内存。

8:有哪两种内存管理机制?

为了管理内存空间,cpu使用了两种内存管理模式:分段和分页,linux同时的采用了分段和分页。

9:何为虚拟地址?

因为虚拟地址是由程序产生的段选择符+段内偏移地址组成,不能直接访问物理内存,而是通过分段之后才行,因此叫做虚拟地址。

虚拟地址由GDT映射的全部空间和LDT映射的局部空间组成。选择符由13位索引部分加上一位GDT和LDT组成,2^14=16384个选择符,每段长度是4GB,则4GB*16384=64TB

何为逻辑地址?

逻辑地址:由程序产生的与段相关的偏移地址,保护模式下,即为程序执行的段限长内的偏移地址。应用程序只需要和逻辑地址打交道。

何为线性地址?

线性地址:线性地址是虚拟地址到物理地址转换之间中间层。是处理器可以寻址的内存空间中的地址。

程序产生逻辑地址,即为段限长的地址加上相应的基地址就产生了一个线性地址。

物理地址:cpu外部的地址总线寻址物理内存的地址信号,是地址转换后的最终地址。

10:linux中为每个程序(进程)换分了多少的虚拟内存空间?

64M

11:程序如何引用一个内存地址?

程序的产生的物理地址通过分段映射到到中间层的2^32即为4GB的线性地址空间中,程序每次对内存的引用都是对内存段中内存的引用。当程序引用一个内存地址的时候,将程序可以看见的逻辑地址加上相应的段基址组成一个线性地址。变成物理地址后送到CPU的外部地址总线上。

12:cpu为什么进行地址转换?

主要的目的是解决虚拟内存空间到物理内存空间的映射问题。

14:虚拟内存的管理怎样实现?

主要采用的就是缺页机制。

当引用了一个不在内存中的页面时,也即是此页面已经被标注成不存在内存中,那么就会出现缺页中断,此时将所缺页面的线性地址放在CR2中,因此中断过程就知道缺页的具体位置,然后将进城所需要的页面从二级存储空间(比如硬盘中)读到物理内存,如果物理内存已经满了,就利用二级存储的一部分作为swapper区,将内存中暂时不用的页面存储在swapper中,将要求的页面调到物理内存中。

15:实模式下的寻址方式是什么?

实模式内存寻址主要的就是利用段和偏移值,段值被放在段寄存器(例如ds),并且段的长度固定64kb,段内偏移地址存放在任意的一个可以用于寻址的寄存器中。

16保护模式下的寻址方式是什么?

保护运行方式下,段寄存器存放的不是被寻址的基地址,而是一个段描述符表(SDT)某一个描述符项的索引值,索引值指向的段描述符项中含有需要寻址的内存段中的基地址,段的长度值(由段的内容决定,可以变的)和段的访问特权级。也是段基址加上偏移量。

17:为什么有此实模式和保护模式的区别?

在于保护模式下的访问的内容多一些。

18:描述符表中的描述符表有哪些内容?

每个描述符项占8个字节,含有描述符段在线性地址空间中的其实地址,段的长度,段的类型(代码段和数据段),段的特权级。一个段最多可以定义为4GB

19:段描述符表有几种,分别有哪些

作用?

有三种:GDT:可以被所有的程序用于引用访问一个内存段。

IDT:替代8086系统中的中断向量表,保存有定义中断和异常处理过程的段描述符。

LDT:为了可以在80x86的保护模式下运行,还定义了GDT和LDT

LDT是GDT的衍生,因为每一个任务都有自己特有的LDT,LDT也为每个任务增加了特有的可用描述符的选项,可以寻址的内存范围,这些表可以保存在线性地址空间的任何地方。

为了快速定位这些段,使用了三种寄存器。GDTR,LDTR和IDTR。寄存器存储表的32位线性基地址和表的限长。

20:cpu怎么寻址一个段?

使用16位的段寄存器中选择符来定位一个段描述符。段选择符中2(T1)用来指示使用那个表,若该位是0则为GDT中表,否则为LDT中的表

21:为什么段寻址这么重要?

因为每个程序都由若干个内存段组成,程序的逻辑地址(或称为虚拟地址)即是寻址这些段和段中的具体的地址位置。程序的逻辑地址到线性地址的变换过程中使用了LDT和GDT,LDT映射的地址空间为局部地址空间,GDT映射的地址空间为全局地址空间,这两者构成了虚拟地址空间。

22:每个LDT和TSS也是GDT描述符定义的中的一个内存段。LDT很短,只有24B。中断描述符表idt保存在内核代码段中,因为代码段和数据段被映射到相同的基地址处,所以内核和各任务的代码段和数据段分别重叠。

23:简述任务状态段TSS的功能;

其功能是:在任务切换时,CPU自动保存或者恢复相关任务的当前进程上下文(cpu当前的状态),例如切换出去,cpu会把寄存器的信息保存在该任务的TSS段中,同时cpu把新切换出去的任务的TSS段中的信息保存在各寄存器。

24:分页机制最普遍的场合是?

使用分页机制最常见的就是当内存被分成很多凌乱的块时,它可以建立起一个大而连续的内存映像,好让程序不必担心管理这些分散的块。但是分页模式不会取代分段模式,而只是一种进一步的检查。

25:内存分页机制的基本原理是?

CPU将整个线性的空间分成4kb的为一页的页面。程序申请内存时候,系统以页为单位分配。CR0的最高位31位置位

26:为什么使用页目录和页表?

为了让线性地址映射到容量较小的物理内存上,使用页目录和页表。一个页目录有1024个页表

都为4kb,其区别是页表项有个已写位Dirty,页目录没有

27:一个页目录表可以映射多大的空间?

CR3保存当前页目录表在物理内存中的基地址,一个页表有1024项,每项为4kb,一个页表最多可以有1024*4kb=4MB的大小的内存,而一个页目录表

最多有1024项,对应1024项页表。因此一个页目录表最多可以映射4MB*1024=4GB的大小的空间。

内核和所有任务共享一个页目录表。

28:怎么将任务的虚拟地址空间转到物理地址空间?

一个任务的虚拟地址需要首先通过其局部的段描述符转换为CPU整个线性地址空间的地址,然后再使用页目录表和页表映射到实际的物理地址空间中。linux把每个进程的最大的虚拟地址空间定义为64MB,因此每个进程的逻辑地址加上64Mb即可转换为线性地址。

29:GDT的使用细分为?

GDT中的段描述符项数最大为256,其中2项空闲,2项系统使用,每个进程使用两项。因此最大共有126个进程。使用的虚拟地址空间范围为126*64MB=8GB,但是人工定义的为64个任务,因此范围最大虚拟范围为4GB。

30:虚拟地址空间中的各任务所占的空间情况?

内核的代码段和数据段被映射到地址空间的最开始16MB部分,任务0,也就是第一个任务的代码段和数据段长度是从线性地址的0开始的640kb范围,其代码和数据段也重叠,并且与内核的代码段和数据段也有重叠。

实际上,linux所有的任务(也即每个进程的所有代码和数据,堆栈部分都处于同一内存段)的指令空间和数据空间都何用一个内存。

任务1的线性地址范围也只有从64MB开始的640kb长度。任务2和任务3分别映射到线性地址128和192MB的开始的地方。

32:cpu多任务和保护方式是什么?

内核代码和数据都放在全局地址空间本身会被所有的任务共有,而每个任务都有自己独有的代码和数据区,任务之间的代码和数据被外围划成多个扇区,相互的隔离。

33:进程的用户态和内核态的解释?

当进程执行系统调用而陷入内核代码执行时候,称之为内核态,此时进程使用进程在内核中的栈,当进程执行用户自己的代码时候,被称为用户态。当进程执行用户程序而被中断打断时候,此时进程象征性的进入内核态,因为进程现在使用的是自己的进程内核栈。

34:在head.s程序的初始化操作中已经将内核代码和数据代码的长度设为16MB的段,重叠的,0~0xFFFFFF。在该范围中含有所有的内核代码,内核段表(GDT,LDT,TSS),页目录表和内核的二级表,内核的局部数据以及内核的临时堆栈(作为第一个任务即任务0的用户堆栈),页目录表和二级页表已经被设置成0-16MB的线性地址空间一一对应到物理地址上,占用了四个目录表,即四个二级页表(一个页表是1024个页,一个也是4k,4k*1024=4MB),因此对于内核或数据的地址来说,我们可以直接把他们看作是物理内存中的地址。

内核管理综合:

默认情况下,linux0.11内核最多管理4096个页面,即16M的空间

1;内核中的数据和代码区在线性地址中空间和物理地址空间是一样的,因此可以大大简化初始化的操作。

2:GDT和LDT在内核的代码区中,因此线性地址和物理地址也是一一对应的

3:我们在setup.s程序的初始化中,我们曾经设置过临时的LDT和GDT,但是当时两个表大概处于0x90200处,进入保护模式后内核系统模块处于0开始处,并且0x90200处的空间被用作缓冲区。因此在进入保护模式下后head.s会重新的设置两个表,即设置GDTR和IDTR指向新的GDT和LDT,描述符也得重新加载。

4:除任务0以外,所有的任务所需要的物理内存页面和线性地址中的不同或部分不同,因此内核需要动态的在主内存区中为他们做映射操作。动态的建立页目录项和页表项。虽然任务1的代码和数据也在内核中,但是由于

它需要另行分配内存,因此也需要自己的映射表。

总结

cpu虽然默认的管理16M的内存,但是系统并不是一定要有这些物理内存,机器有的只需要4M或者2M,因此4-16M的线性地址不会映射到物理地址上,初始的时候就会知道物理内存容量的具体大小,因此分页机制不会映射到4-16M,但是由于int/main.c程序初始化限制了16MB以上的内存使用。因此16MB以上的物理内存不会用到。如果我们能对main.c进行更改,那么我们就需要在内核数据段和代码段建立8个二级页表来把32M的线性地址空间映射到物理地址空间。

三个初始任务的关系。

任务0:是人工初始化的,代码段和数据段从0开始的640kb,对应的TSS0任务状态段也是手工预置的,并且位于任务0数据信息结构中,TSS0段位于内核的sched.c程序的代码中,长度为104字节。任务0直接包含在内核代码中,不需要为其分配额外的内存页面,它运行时所需要的内核态堆栈和用户态堆栈空间也在内核代码区域中。

任务1:代码也在内核的代码区域中,与任务0不同的是系统用fork()创建任务1时为了存放任务1的二级页表而在主存中申请了一页内存来存放,并且复制了父进程(任务0)的页目录和二级页表项。但是任务1的长度也是640kb,实际上是64MB~64MB+640kb,也映射到了任务0开始的0-640kb,只要是写时复制技术,但是系统也会在主内存区域申请一页内存,用来存放它的任务数据结构,并用作任务1的内核堆栈空间。当任务开始执行的时候,0和1的公用用户堆栈被设置成只读,然后产生缺页,也就内核分配主存区域作为堆栈使用。

任务2开始的其他任务

从任务2的任务他们的父进程都是任务1,线性地址空间都是64MB*n,共有16个页目录项。

在任务2被创建出来之后,将在其中运行execve()函数来执行shell程序。当2被1复制后,除了占用线性地址空间不同128M~128M+640kb,数据和代码的在地址空间与1完全相同。

当任务2的代码(init())调用execve()系统调用开始加载并执行shell程序时候,该系统调用会释放从任务1复制的页目录和页表项以及相关的内存页面,然后为新的执行程序shell设置相关的页目录和页表项。

注意在执行execve()函数时候,系统虽然在线性地址空间为任务2分配了64MB的空间范围,但是内核并不会立刻为其分配和映射物理页面。只有当任务2开始执行的时候由于发生缺页中断异常,才会由内存管理程序为其在主内存区域分配并且映射一页的物理内存到线性的地址空间中。

35:malloc的内存分配

当用使用c函数库中的内存分配函数malloc()申请内存时候,这些动态的申请内存容量大小由高层次的c库函数malloc()进行管理。内核不插手,因为内核已经为每个任务在线性地址空间分配了64MB的地址空间,但系统会为每个任务设置一个brk,brk代表的就是每个任务的数据段和代码段在线性地址空间的中当前末端的位置,brk保存在进程的数据结构中,当malloc()函数为程序分配内存的时候,他会通知系统调用brk把程序要求新增的空间长度通知给内核,内核来更新brk的位置。但是此时不会新申请的空间映射到物理地址上,只有当程序发生缺页中断的时候才可以映射到物理地址。

内核以页为单位分配和映射物理地址内存,该函数具体的记录用户程序使用了一页的多少字节,剩余的容量将保留给程序再申请时候用。当使用free()函数的时候,c库中的内存管理函数就会将这块设置为空闲,但是物理地址不会被释放掉,为了方便下次的再次申请,只有进程在最终结束的时候才会释放映射到的物理内存页面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值