一.内存管理
1.管理模型
(1)一方面是虚拟地址到物理地址的映射
(2)另一方面是物理内存的分配
以上就是内存管理子系统的职能
2.地址引射管理
(0)程序中用虚拟地址,实际访问硬件必须用物理地址,所以存在映射关系。
(1)CPU和内存重要却有限
(2)虚拟地址空间分布(空间大小由硬件决定)
==》用户空间0-3GB
==》内核空间3GB-4GB
==》直接映射空间3GB—3GB+896MB。虚拟地址 = 3GB + 物理地址。物理内存的低896MB称为低端内存,896MB以上称之为高端内存区。直接映射区对应低端内存区。
==》vmallot区,即可以访问低端,又可以访问高端。虚拟地址和物理地址没有很紧密的线性关系。
==》永久内存映射区,固定访问高端内存。
==》固定映射区,和特殊寄存器建立对应关系。
(3)地址映射(涉及到裸机的MMU部分)
3.物理内存分配管理
(1)什么时候分配物理内存?一般情况malloc和new会分配,但是在Linux上并非如此,因为Linux实行的是虚拟地址管理。malloc和new得到的是虚拟地址,有了虚拟地址并不一定就有对应的内存空间。
(2)只有当访问虚拟地址的时候才会分配物理内存,这样可以避免浪费。
(3)malloc和fork以及excute和mmap等函数都是只先得到虚拟地址,并没有实际的物理地址与之对应。当我们去访问这个虚拟地址,他会将其转换为物理地址,此时Linux内核发现没有与之对应的物理内存。于是引发缺页异常,再去看页框(页帧)有无空闲的物理内存,有的话就分配空闲的物理内存与虚拟地址建立对应关系。
(4)凡是缺页异常的都是先得到虚拟地址,并没有得到实际的物理内存。
(5)但是如果在内核里面用kmalloc的话,返回的虚拟地址就和一段物理内存已经对应好了。这也就是传说中slap管理器的功能。slap先从空闲的内存中去一部分放到自己的池子中,当使用kmalloc的时候,就从池子里面拿出一部分给返回值(地址)。
二.进程管理子系统
包括进程的要素和调度。
1.进程与程序
程序:一系列代码和数据构成的可执行文件,是静止的实体。
进程:运行中的程序,是动态的实体。
2.进程四要素:
(1)有一段可供执行的程序,这段程序不一定是专用的,有可能和其他进程共享。
(2)有进程专用的内核空间堆栈。
(3)由PCB(进程控制块),即拥有一个task_struct结构体,使其成为内核可以调度的最小单位。
(4)有独立的用户空间。
(5)另外如果没有独立的用户空间,有共享的用户空间,则称之为用户线程。但是如果什么类型的用户空间都没有的话,就是内核线程。
3.进程状态
(1)就绪
(2)执行
(3)阻塞
以上是主要的,但是在Linux中远不止这些。
(4)task_running
相当于就绪和执行,进程一旦被创建就处于该状态
(5)task_interruptible
可被中断或者其他进程发送的信号唤醒的阻塞态
(6)task_uninterruptible
不可被中断或者其他进程唤醒,除非是资源释放。
(7)task_killable
Linux2.6.25中新引入的,为的就是避免task_uninterruptible的尴尬,能够接受比如SIGKILL等一部分信号从而唤醒。
(8)task_traced
被调试的进程
(9)task_dead
进程退出时所处的状态
4.进程描述
(1)进程和用户线程以及内核线程都是需要用到PCB的。
(2)在task_struct中的重要成员有
5.调度策略
(1)调度就是指在一系列已经就绪的进程中,选择最合适的一个执行的过程。调度策略就是调度的依据。
(2)常见的调度
6.调度时机
(1)schedule()函数就是调度进程。
(2)主动式
在内核中直接调用schedule()函数,进程需要等待资源,此时该进程主动让出CPU,并把自己挂起睡眠,主动请求调度。
(3)被动式(抢占式)
==》用户态抢占
==》抢占发生在
==》从系统调用返回用户空间
==》从中断处理程序返回用户空间
==》抢占条件:在上述时机,need_resched标志被设置
==》当某个进程好近他的时间片,会设置need_resched
==》当一个高优先级进程进入可执行状态也会设置need_resched
==》缺陷是实时性不好,一旦程序进入内核态不返回用户态,用户空间的进程无法执行。除非内核态的进程主动放弃或者时间片耗尽。从而引入了内核态抢占。
==》内核态抢占(2.6版本以后的内核才支持)。允许在内核态高优先级可以抢占低优先级。
==》抢占时机:
==》中断处理完成,返回内核空间之前
==》当内核代码再一次具有可抢占性。比如解锁以及使能软中断。
(4)在以下情况不允许被抢占(尤其是内核态)
a.内核正在运行中断处理
b.内核正在进行中断上下文的bottomhalf处理,硬件中断返回前会执行软中断。此时仍处于中断上下文。
c.进程持有spinlock自旋锁以及writelock/redalock读写锁,否则会死锁。
d.内核正在执行调度程序scheduler。
(5)抢占计数
a.preempt_count就是传说中的内核抢占计数。
b.为了防止上述情况被抢占,每当进入上述情况,改变量加1,推出上述情况就减1.
c.这是一个全局变量,被设置在进程的thread_info结构中。
7.调度步骤(schedule函数的工作流程)
(1)清理当前运行中的进程,比如释放资源
(2)选择下一个要运行的进程,根据调度策略选择
(3)设置新进程的运行环境,设置堆栈指针
(4)进程上下文切换,交接CPU。