Linux内核复习.docx
《Linux内核复习.docx》由会员分享,可在线阅读,更多相关《Linux内核复习.docx(15页珍藏版)》请在冰豆网上搜索。
![Linux内核复习.docx](https://file1.bdocx.com/fileroot1/2023-1/25/346ae656-da25-4049-8a8d-312c9c00840b/346ae656-da25-4049-8a8d-312c9c00840b1.gif)
Linux内核复习
1.内核:
操作系统核心,其组成:
中断服务程序:
负责响应中断
调度程序:
负责管理多个进程分享处理器时间
内存管理程序:
负责管理进程地址空间
系统服务程序:
负责管理网络、进程间通信
2.内核空间:
内核处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限,这种系统态和被保护起来的内存空间,统称为内核空间。
用户空间:
应用程序在用户空间执行,只能使用部分系统及特定的系统功能,不能直接访问硬件、内核划分给别人的内存范围。
3.应用程序、内核和硬件
4.应用程序通过系统调用与内核通信:
5.应用程序与内核通信:
系统调用
系统调用:
应用程序用来与内核通信的接口。
应用程序通常通过调用库函数,再由库函数通过系统调用,让内核代其完成各种不同的任务。
应用程序被称为通过系统调用在内核空间运行,而内核被称为运行于进程上下文中。
6.Linux内核和传统Unix内核的比较
单内核和微内核
单内核:
把它从整体上作为一个单独的大过程来实现,同时也运行在一个单独的地址空间上。
可直接调用函数,大多unix基于单内核
微内核:
功能被划分为多个独立的过程,每个过程叫做一个服务器。
所有服务器独立运行在各自的地址空间上。
通过消息传递处理微内核通信,系统采用了进程间通信(IPC),WindowsNT基于微内核
7.辨析
Linux是单内核,内核运行于单独的内核地址空间上。
但借鉴微内核,采用模块化设计、抢占式内核、支持内核线程及动态装载内核模块的能力,所有事情都运行在内核态,直接调用函数,无需消息传递。
8.Linux与Unix的差异:
●Linux动态加载内核模:
块动态卸除和加载部分内核代码
●Linux支持对称多处理(SMP)机制
●Linux内核支持抢占:
允许在内核运行的任务优先执行的能力,Unix里只有Solaris和IRIX支持抢占
●支持线程,但不区分线程和进程
●Linux提供具有设备类的面向对象的设备模型、热插拔事件及用户的设备文件系统(sysfs)
●忽略Unix的某些拙劣特性
●自由
9.Linux内核版本
Linux内核分为:
稳定和处于开发中的
从版本号为偶数时,代表内核为稳定版;为奇数时,为开发版。
例:
2.6.30.1,其从版本号为6,则为稳定版。
10.进程及作业的概念
●多用户、多任务。
根据每个任务的优先级为每个任务分配时间片
●Linux系统上所有运行的内容都可以称为进程,我们关心的是如何去控制这些进程
●进程与程序,程序静态命令集,进程是动态运行的程序。
一个程序可以启动多个进程
11.进程分为哪几个类型
Linux操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性:
●交互进程:
由shell启动的进程,既可在前台运行,又可在后台运行
●批处理进程:
这种进程和终端没有联系,是一个进程序列。
●守护进程:
在后台持续运行的进程。
12.前后台辨析
前台:
指一个进程控制标准输入和输出。
后台:
一个程序不从标准输入接受输入,也不将结果输出到标准输出上,不经用户干预的程序适合运行在后台。
进程与作业:
一个正在执行的进程称为一个作业,而作业可以包含一个或多个进程,尤其是在使用了管道和重定向命令时。
13.结束进程
前台进程Ctrl+c
后台进程kill命令
使用ps命令查看PID
killPID
kill-9PID无条件地撤销一个进程
14.进程线程区别
进程:
处于执行期的程序。
包含:
可执行的程序代码、打开的文件、挂起的信号、内核内部数据、处理器状态、内存地址空间、一个或多个执行的线程、存放全局变量的数据段。
进程的另一个名字叫任务(task)
线程(thread):
在进程中活动的对象。
每个线程拥有一个独立的程序计数器、进程栈和一组进程寄存器。
内核调度的对象是线程,而不是进程。
15.Linux系统不区分进程和线程,线程只是一种特殊的进程。
进程的创建:
fork()
进程的终结:
exit()
16.进程描述符及任务结构
内核把进程的列表存放在叫做任务队列的双向循环链表中。
链表中的每一项都是类型为task_struct、称为进程描述符(processdescriptor)的结构()。
进程描述符中包含一个具体进程的所有信息:
打开的文件、进程的地址空间、挂起的状态等
17.进程描述符的存放(描述符及功能,辨析的话问是否可以改动)
内核通过一个唯一的进程标识值(processidentificationvalue)或PID来标识每个进程。
PID是一个数,表示为pid_t隐含类型,即int。
为与老版本兼容,默认最大值、为32768,实际可增加到400万,但这个值越小,转一圈就越快。
可通过修改/proc/sys/kernel/pid_max来提高上限。
18.进程家族树
所有的进程都是PID为1的init进程的后代,内核在系统启动的最后阶段启动init进程,该进程读取系统的初始化脚本并执行其他的相关程序,最终完成系统启动的整个过程。
除了init之外,所有进程都是由其他进程创建的。
创建新进程的进程称为新进程的父进程,而被创建的进程称为原进程的子进程。
若两个进程都是由同一个进程创建的,则称这两个进程为兄弟进程。
Task_struct结构中就有进程的父进程指针、兄弟进程指针以及进程的子进程指针。
19.线程在Linux中的实现
线程:
提供在同一程序内共享内存地址空间运行的一组线程。
线程可以共享打开的文件和其他资源,支持并发程序设计技术。
Linux没有线程的概念,所有进程都当作进程来实现,没有特别的调度算法或定义特别的数据结构来表征线程,线程仅视为与其他进程共享某些资源的进程。
线程又称为“轻量级进程”,是一种进程间共享资源的手段。
20.多任务操作系统
同时并发地交互执行多个进程的操作系统。
无论是单处理器或多处理器上,多任务操作系统都能使多个进程处于堵塞或者睡眠状态。
即实际不被投入执行,直到工作确实就绪,这些任务尽管位于内存,但并不处于可运行状态。
21.多任务系统分为:
非抢占式多任务和抢占式多任务(区别)(抢占如何发生)
Linux提供了抢占式的多任务模式,在此模式下,由调度程序来决定什么时候停止一个进程的运行以便其他进程能够得到执行机会。
这个强制的挂起动作就叫做抢占(preemption)。
进程在被抢占之前能够运行的时间是预先设置好的,而且有一个专门的名字,叫进程的时间片(timeslice)。
时间片实际上就是分配给每个进程的处理器时间段。
有效管理时间片能使调度程序从系统全局的角度做出调度决定,这样做还可以避免个别进程独占系统资源。
非抢占式多模式下,除非进程自己主动停止运行,否则它会一直执行。
22.策略:
决定调度程序在何时让什么进程运行
进程分类:
I/O消耗型和处理器消耗型的进程
I/O消耗型:
进程大部分时间用来提交I/O请求或等待I/O请求例:
用户图形界面程序属于I/O密集型
处理器消耗型:
多数时间用在执行代码上。
例:
执行数学计算的程序,如MATLAB
●调度策略的目的:
进程响应迅速和最大系统利用率
●Linux为了保证交互式应用,更倾向于优先调度I/O消耗型进程。
23.Linux采用两种不同的优先级范围:
●nice值,-20~+19,nice值越大意味着优先级越低,获得处理器的时间越少。
Linux中,nice值代表时间片的比例,PS–el命令结果中标记NI的一列就是进程对应的nice值
●实时优先级:
0~99,越高的实时优先级数值进程优先级越高。
任何实时进程的优先级都高于普通的进程。
24.时间片(进程抢占对时间片的影响)
定义:
时间片是一个数值,它表明进程在被抢占前所能持续运行的时间。
调度策略必须规定一个默认的时间片
◆时间片过长:
导致系统对交互的响应表现欠佳;
◆时间片太短:
会明显增大进程切换带来的处理器耗时。
◆I/O消耗型不需要长的时间片,而处理器消耗型正相反
◆Linux将处理器的使用比划分给进程,即进程所获得的处理时间和系统负载相关,同时也受nice的影响
◆当一个进程的时间片耗尽时,就认为进程到期了。
◆没有时间片的进程不会再投入运行,除非等到其它所有的进程都耗尽了它们的时间片,这时,会重新计算所有进程的时间片
25.进程抢占
两种情况下会发生进程抢占:
●有一个进程进入TASK_RUNNING状态,而它的优先级高于当前正在运行的进程
●当正在运行的进程的时间片变为0时
26.CFS算法(非实时)
●准确计算每个进程在全部可运行进程中所占比例的时间片,CFS为多任务设立无限小的调度周期,称为目标延迟。
越小的调度周期交互性越好,切换代价越高及系统总吞吐能力越差
●当可运行任务数量趋于无限时,CFS引入每个进程获得的时间片的最小粒度,默认值为1ms
●绝对的nice值不再影响调试策略,相对的nice值影响处理器时间的分配比例
27.实时调度策略
●SCHED_FIFO:
实时调度策略,先到先服务。
一旦占用cpu则一直运行。
一直运行直到有更高优先级任务到达或自己放弃
●SCHED_RR:
实时调度策略,时间片轮转。
当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。
放在队列尾保证了所有具有相同优先级的RR任务的调度公平Linux线程优先级设置
28.系统调用在用户空间进程和硬件设备之间,作用:
●为用户空间提供了硬件的抽象接口
●保证系统的稳定和安全
●使用用户运行在虚拟系统中,实现多任务和虚拟内存
系统调用是访问内核的唯一手段
29.POSIX
POSIX是Unix中最流行的应用编程接口,由IEEE的一组标准组成。
目标是提供基于Unix的可移植操作系统标准。
(LinuxとUnix用什么手段达到可移植?
用了POSIX接口)
30.系统调用
●系统调用号:
唯一关联一个系统调用,一旦分配就不能变更。
X86-64中,定义于arch/i386/kernel/syscall_64.c
●系统调用的性能:
Linux系统调用比其它操作系统执行速度快,上下文切换时间短,进入内核简洁高效
31.内核最常用的数据结构:
链表队列映射二叉树
32.各链表比较
33.Linux内核中的实现(理解内核链表方式使用的不同)
Linux内核方式不是将数据结构塞入链表,而是将链表节点塞入数据结构,链表的实现要依据官方内核链表实现
34.队列
生产者-消费者模式:
例生产者创造数据(需要读取的错误信息或需要处理的网络包),消费者读取消息和处理包。
35.映射
映射:
关联数组,由唯一键组成的集合,每个键必然关联一个特定的值,这种键到值的关联关系称为映射。
映射支持三种操作:
●Add(key,value)
●Remove(key)
●value=Lookup(key)
Linux映射的目标:
映射一个唯一标识数(UID)到一个指针。
映射命名为idr
36.数据结构以及选择
Linux最重要的数据结构:
●链表:
对数据集合的主要操作,存储一个大小不明确的数据集合
●队列:
代码符合生产者/消费者模式,或需要一个定长的缓冲
●映射:
映射一个UID到一个对象
●红黑树:
存储大量数据,并需要快速检索
37.中断处理:
内核如何对外围硬件设备有效管理
●处理器向硬件发送一个请求,处理器的速度比外围硬件设备快,处理器需等待回应
●轮询(polling)方法,让内核定期对设备的状态进行查询,但容易做无用功,设备可能忙碌或空闲
●硬件在需要时候向内核发送信号,即中断机制
38.中断(如何产生)
●中断使硬件发出通知给处理器,中断本质是一种特殊的电信号,由硬件设备发向处理器。
处理器收到中断后,会马上向操作系统反映此信号的到来,然后就由操作系统负责处理这些新到来的数据,中断随时产生,内核随时可能因为新到来的中断而打断。
●不同的设备对应的中断不同,每个中断由唯一的数字标识。
从而,操作系统对中断进行区分,为不同的中断提供不同的中断处理程序
39.中断处理程序
●在响应一个特定中断的时候,内核会执行一个函数,该函数叫做中断处理程序(interupthandle)或中断服务例程(interruptserviceroutine,ISR)。
产生中断的每个设备都有一个相应的中断处理程序。
中断处理程序是设备驱动程序的一部分。
●与C函数的区别:
必须按照特定的类型声明;被内核调用来响应中断的,运行于中断上下文的特殊上下文中。
一个设备的中断处理程序是设备驱动程序的一部分-设备驱动程序是用于对设备进行管理的内核代码。
●中断处理程序要求:
快速执行,保证尽可能地恢复中断代码的执行。
40.上半部与下半部的对比
●上半部(tophalf)—接收到一个中断,立即开始执行,只做有严格时限的工作。
例如对接收的中断进行应答或复位硬件。
●下半部(bottomhalf)—完成上半部未完成的处理工作,通常情况下,下半部会在中断处理程序返回时立即执行。
41.共享的中断处理程序
共享与非共享的处理程序的差异:
●request_irq()的参数flags必须设置SA_SHARED标志;
●对每个注册的中断处理程序来说,dev参数必须唯一。
指向任一设备结构的指针就可以满足这一要求;通常会选择设备结构,因为它是唯一的,而且中断处理程序可能会用到它。
不能给共享的处理程序传递NULL值。
●中断处理程序必须能够区分它的设备是否真的产生了中断。
这既需要硬件的支持,也需要处理程序中相关的处理逻辑。
如果硬件不支持这一功能,那中断处理程充就无法知道与它对应的设备发出了这个中断。
还是共享这条中断的其他设备发出了这个中断。
42.中断处理机制的实现
第八章下半部和推后执行的工作
43.下半部
下半部(bottomhalf)的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作。
对于上半部和下半部之间划分工作没有严格规则,但可遵循以下几点规则:
●如果是一个任务对时间非常敏感,将其放在中断处理程序中执行;
●如果一个任务与硬件相关,将其放在中断处理程序中执行;
●如果一个任务要保证不被其它中断打断,将其放在中断处理程序中执行;
●其他所有任务,考虑放置在下半部执行;
44.下半部的环境
内核提供三个不同形式的下半部实现机制:
软中断tasklets工作队列
其中,软中断使用的比较少,tasklets是下半部最常用的方法
45.
软中断保留给系统中对时间要求最严格以及最重要的下半部使用,目前,只有网络和SCSI子系统直接使用软中断
46.ksoftirqd
问题:
软中断被触发的频率可能会很高,处理函数有时还会自行重复触发,也就是说,当一个软中断执行的时候,它可以重新触发自己以便再次得到执行。
如果软中断本身出现的频率过高,再加上它们又有将自己重新设置为可执行状态的能力,就会导致用户空间进程无法获得足够的处理器时间,因而处于饥饿状态。
而单纯对重新触发的软中断采取不立即处理的策略也不是很理想的方案,这是一个亟待解决的问题
方案一:
只要还有被触发并等待处理的软中断,本次执行就会负责处理,重新触发的软中断也在本次执行返回前被处理。
这样可以保证对内核的软中断采取即时处理的方式。
但当负载很高的时候会出问题,用户空间被忽略了,这种方案只有系统处于低负载的情况下,才会有理想的运行效果。
方案二:
选择不处理重新触发的软中断。
在从中断返回的时候,内核和平常一样,也会检查所有挂起的软中断并处理它们,但是,任何自行重新触发的软中断都不会马上处理,被放到下一个软中断执行时机去处理。
但在比较空闲的系统中,这种方案就不是很好。
尽管它能保证用户空间不处于饥饿状态,但它却让软中断忍受饥饿的痛苦,根本没有好好利用闲置的系统资源。
实际方案:
不立即处理重新触发的软中断。
而作为改进,当大量软中断出现的时候,内核会唤醒一组内核线程来处理这些负载。
这些线程在最低的优先级上运行,这能避免它们跟其他重要的任务抢夺资源。
但它们最终肯定会被执行,所以,这个方案能够保证在软中断负担很重的时候用户程序不会因为得不到处理时间而处于饥饿状态。
相应的,也能保证“过量”的软中断终究会得到处理。
最后,在空闲系统上,这个方案表现良好,软中断处理得非常迅速(因为仅存的内核线程偿会马上调度.)
47.临界区和竞争条件
●临界区:
访问和操作共享数据的代码段。
●竞争条件:
两个执行线程处于同一临界区中同时执行,存在线程竞争。
●同步:
避免并发和防止竞争条件称为同步
48.单个变量
全局整形变量i,执行的操作为i++,其机器指令序列:
●得到当前变量i的值并且拷贝到一个寄存器中
●将寄存器的值加1
●把i的新值写回到内存中
49.死锁
产生条件:
有一个或多个执行线程和一个或多个资源,每个线程都在等待其中的一个资源,但所有的资源都已被占用,所有线程都在相互等待,但永远不会释放已经占用的资源,死锁发生。
50.原子操作
●原子操作可以保证指令以原子的方式被执行,操作过程不被打断
●两个原子操作绝对不可能并发地访问同一个变量
51.自旋锁
●自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分,而对于单处理器来说,可简单采用关闭中断的方式防止中断处理程序的并发执行
●设计自旋锁的初衷是在短期间内进行轻量级的锁定。
一个被持有的自旋锁使得请求它的任务在等待锁重新可用期间进行自旋,所以自旋锁不应该被持有时间过长
●自旋锁不允许任务睡眠,持有自旋锁的任务睡眠会造成自死锁,因此自旋锁能够在中断上下文中使用
52.自旋锁与信号量的比较
53.地址空间(知道两个就行)
地址空间(addressspace)是一段表示内存位置的地址范围
地址空间有两种:
●物理地址空间是指由程序产生的与段相关的偏移地址部分。
●逻辑地址空间,也被称为虚拟地址空间是使用物理地址总线中的位表示的地址。
物理地址可能与逻辑地址不同,内存管理单元可以将逻辑地址转换成物理地址。
54.逻辑地址和物理地址之间的转换
在逻辑地址和物理地址之间相互转换的工作是由内核和硬件内存管理单元(MMU—memorymanagementunit)共同完成的MMU是被集成进现代的CPU里的,它们都是同一块CPU芯片内的一个部分。
内核告诉MMU如何为每个进程把某逻辑页面映射到某特定物理页面,而MMU在进程提出内存请求时完成实际的转换工作
55.页
●物理页是内存管理的基本单位。
●内存管理单位MMU以页大小为单位管理系统中的页表
●不同体系结构支持的页的大小不同,32位支持4KB,64位支持8KB
●structpage结构表示系统中的每个物理页,定义于
56.
page结构对物理页的描述是短暂的,内核仅用page结构描述物理内存,而不是包含其中的数据。
内核用page结构管理系统中所有的页,包括页是否空闲,拥有的用户进程、动态分配的内核数据、静态内核代码或页高速缓存等。
57.区
内核把页划分为不同的区(zone),区对具有相似特征的页进行分组
58.kmalloc()
获得以字节为单位的一块内核内存,函数返回一个指向内存块的指针,其内存块至少有size大小,分配的内存区在物理上连续的。
出错时,返回值为NULL,除非没有足够的内存,否则内核总能分配成功。
59.slab层
分配和释放数据结构:
当代码需数据结构实例时,可从空闲链表中获得,不需分配内存,空闲链表包含分配好的数据结构块。
空闲链表是对象高速缓存-快速存储频繁使用的对象类型。
60.虚拟文件系统功能
●记录操作系统中可以支持和已经安装有哪些文件系统类型,
●将相关系统调用转换为对具体类型文件系统的调用,
●负责不同类型文件系统间的协同工作(例如跨FS复制),
●实现对不同类型文件系统的动态装卸和可扩充性等。
61.区别
文件系统是数据分层存储结构,包含文件、目录和相关的控制信息。
通用操作包含创建、删除和安装等。
文件系统被安装在一个特定的安装点上,该安装点在全局层次结构中称为命名空间,已安装文件系统作为根文件系统树的枝叶。
类Unix操作采取单一、统一的树形管理文件系统
62.VFS对象及其数据结构
VFS有四个主要的对象类型:
●超级块对象,代表一个具体的已安装文件系统
●索引节点对象,代表一个具体文件
●目录项对象,代表一个目录项,是路径的一个组成部分
●文件对象,代表由进程打开的文件
63.块设备和字符设备区别
块设备:
系统中能够随机访问固定大小数据片的硬件设备称作块设备。
固定大小的数据片称为块,例如常见的块设备是硬盘,软盘驱动器、蓝光光驱和闪存等。
访问方式都是以安装文件系统的方式
字符设备:
字符设备按照字符流的方式被有序访问,例如串口和键盘
64.块设备
块设备中最小的可寻址单元是扇区,扇区大小一般是2的整数倍,最常见为512字节。
扇区的大小是设备的物理属性,块大小是扇区大小的2的整数倍,并且小于页面大小,块大小是512字节、1KB或4KB
65.I/O调度程序与进程调度程序的区别:
●进程调度程序是将处理器资源分配给系统的运行进程
●I/O调度程序虚拟块设备给多个磁盘请求,以降低磁盘寻址时间,确保磁盘性能的最优化
66.Linus电梯
Linus电梯执行合并与排序预处理。
当一个请求加入到队列中时,可发生以下四种操作
●如果队列中已存在一个对相邻磁盘扇区操作的请求,那么新请求将和这个已经存在的请求合并成一个请求
●如果队列中存在一个驻留时间过长的请求,那么新请求将被插入到队列尾部,以防止其他旧的请求饥饿发生
●如果队列中以扇区方向为序存在合适的插入位置,那么新的请求将被插入到该位置,保证队列中的请求是以被访问磁盘物理位置为序进行排列的
●如果队列中不存在合适的请求插入位置,请求将被插入到队列尾部
67.最终期限I/O调度程序
●Linus电梯可以提供更好的系统吞吐量,但它总按照扇区顺序将请求插入到队列,从不检查驻留时间过长的请求,所以它虽然能让寻址时间最短。
但对磁盘同一位置操作的请求流可以造成较远位置的其他请求得不到运行机会,带来请求饥饿问题
●最终期限I/O调度程序为解决Linus电梯的饥饿问题。
每个请求都有一个超时时间,读请求的超时时间默认是500ms,写请求的超时时间默认是5s。
最终期限I/O调度请求类似于Linus电梯,以磁盘物理位置次序维护请求队列。
但同时以请求类型为依据将它们插入到额外队列中,读/写请求按次序分别被插入到特定的读/写FIFO队列中。
●对普通操作,最后期限I/O调度程序按排序队列提交给磁盘驱动。
在写或读FIFO队列头的请求超时,当前时间超过了请求超时,调度程序从FIFO队列中提取请求进行服务,试图保证不会发生明显超时得不到服务的现象,降低了读操作响应时间。
68.最终期限I/O调度程序的三个队列
69.预测I/O调度程序
●实现方法:
预测I/O调度程序调度基础仍是最终期限I/O调度程序,增加了预测启发能力。
减少在进行I/O操作期间,处理新到的读请求所带来的寻址数量。
请求提交后并不直接返回处理其他请求,空闲片刻(默认6ms),应用程序可以提交读请求,任何对相邻磁盘位置操作的请求都会立刻得到处理。
等待时间结束后,继续执行以前剩下的请求。
●优势:
依靠一系列的启发和统计工作,跟踪并统计每个应用程序块I/O操作