Linux复习大纲带答案_学长版_(3)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《实用操作系统》期末考试题型说明
2016年6月16日
一、名词解释(共5题,每题3分,计15分)
通过2~3句话说明相关概念的基本定义。
二、计算题(共2题,每题15分,计30分)
结合相应图表,根据题目要求,计算相应结果(给出详细计算过程,分步给分)。
三、简答题(共5题,每题6分,计30分)
根据提问,对相关知识点进行总结,并作必要对比分析。
四、程序分析题(共2题,每题7分,计14分)
根据相关代码框架,说明相应技术的实现原理与机制(不需要对代码细节做深入分析)。
五、程序设计题(共1题,计11分)
根据题目要求,给出相应的设计方案。
《实用操作系统》复习提纲
提示:
1)请根据以下提纲整理相关知识内容的要点,避免去死记硬背。
2)请不要简单地依据往年试题内容复习,否则后果自负。
第一讲:Linux系统分析基础
1、什么是用户态和内核态及划分的必要性?
不区分的缺陷
用户直接修改操作系统数据
用户直接调用操作系统内部函数
用户直接操作外设
用户任意读/写物理内存
区分意义:保护内核
禁止用户程序和底层硬件直接打交道
如果用户程序往硬件控制寄存器写入不恰当的值,可能导致硬件无法正常工作
禁止用户程序访问任意物理内存,否则可能会破坏其他程序的正常执行
如果对核心内核所在的地址空间写入数据,会导致系统崩溃
2、Linux单内核、多模块的特点及其与微内核操作系统的主要区别。
Linux是单内核、多模块系统
Linux内核运行在单独的内核地址空间
所有操作系统功能作为一个模块实现在内核中
模块均运行在内核态,直接调用函数,无需消息传递
模块化设计、抢占式(Linux 2.6内核级抢占,Linux 2.4用户级抢占)、支持内核线程及动态装载内核模块的能力
与Unix主要区别
Unix也是单内核系统,但Linux汲取了微内核设计思想(基于模块定制内核)
Unix也是单内核系统
Windows NT和Mach是微内核系统
只提供基础功能,其他功能通过服务实现
微内核被划分为多个独立过程,每个过程称为服务器
3、可加载内核模块的概念,内核模块与C语言应用程序的主要差别。
加载内核模块(Loadable Kernel Module)的概念
模块实际上是一种目标对象文件,没有链接,不能独立运行
其代码可以在系统运行时链接到系统中,作为内核的一部分运行或从内核中取下,从而可以动态扩充内核的功能(不需要重新编译内核)
这种目标代码通常由一组函数和数据结构组成
C语言程序模块
运行用户空间内核空间
入口main() module_init()
出口无module_exit()
编译gcc -c 编制专用Makefule,并调用gcc 连接gcc insmod
运行直接运行insmod
调试gdb kdbug, kdb, kgdb等
第二讲:进程与线程
1、Linux 2.4及2.6进程系统堆栈结构特点及主要区别。
Linux进程系统堆栈结构特点
➢8192(213 )字节,两个页框
➢占据连续两个页框,且第一个页框起始地址为213的倍数
Linux2.4进程系统堆栈结构特点
结构定义(/include/linux/sched.h)
Linux2.6进程系统堆栈数据结构定义
(其定义了一个指向进程描述符的指针)Linux2.6进程系统堆栈结构特点
两者区别:
➢Linux2.4进程描述符由alloc_task_struct(),free_task_struct(),get_task_struct()进行管理,Linux2.6进程描述符由slab分配器动态生成;
➢Linux2.4进程系统堆栈栈底使用struct task_struct结构,Linux2.6进程系统堆栈栈底使用新结构struct thread_info,其定义了指向进程描述符的指针,占用更小的栈空间
2、进程(组)相关标识符的含义。
·成员名:pid_t pid
功能:
内核通过pid标识每个进程
pid与进程描述符之间有严格的一一对应关系
·成员名:pid_t tgid
功能:
标识进程是否属于同组,组ID是第一个组内线程(父进程)的ID
线程组中的所有线程共享相同的PID
3、idle进程。
系统引导进程(init_task)在引导结束后成为cpu 0上的idle进程,每个cpu上都有一个idle进程,idle进程不进入就绪队列,仅当就绪队列为空时idle进程才会被调度。
4、通用内核链表的设计特点及与双向链表的主要区别。
特点:
➢链表结构作为一个成员嵌入到宿主数据结构内
➢链表结构可放在宿主结构内的任何位置
➢一个宿主结构可有多个内核链表结构
➢避免为每个数据项类型定义自己的链表
通用内核链表不用为每个数据项定义链表。
传统双向链表的指针记录节点的首地址,通用内核链表的指针记录链表的地址。
6、“RCU”的特点与作用。
特点:
·以“_rcu”结尾的宏
·通过延迟写操作来提高同步性能
作用:
·RCU常用来保护读操作占多数的链表与数组
7、常用进程创建函数的主要差别及使用方法。
进程创建函数
·pid_t fork(void);
·pid_t vfork(void);
·int clone(int (*fn)(void * arg), void *stack, int flags, void * arg);
关系差别
①fork, vfork and clone三者最终都会调用do_fork函数。
②Vfork()与fork()功能相同,但vfork()但不拷贝父进程的页表项。
子进程只执行exec()时,vfork()为首选。
而对于clone()是创建轻量级线程的。
它是fork()的推广形式,它允许新进程共享父进程的存储空间、文件描述符和信号处
使用:(个人觉得略坑)
do_fork(unsigned long clone_flag, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int _user *parent_tidptr, int _user *child_tidptr);
参数说明
clone_flag:子进程创建相关标志
stact_start:子进程用户态堆栈的地址,将用户态堆栈指针赋给子进程的esp
regs:从用户态切换至内核态时保存用户堆栈到内核态的堆栈
stack_size:未使用(总设为0)
parent_tidptr:父进程用户态下的PID地址,若需父进程与新轻量级进程有相同PID,则需设置CLONE_PARENT_SETTID
child_tidptr:新建子进程用户态下的PID,若需让新进程具有同类进程的PID,需设置
CLONE_CHILD_SETTID 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
说明
vfork()创建的子进程与父进程共享地址空间
子进程作为父进程的一个单独线程在其地址空间运行
子进程从父进程继承控制终端、信号标志位、可访问的主存区、环境变量和其他资源分配
子进程对虚拟空间任何数据的修改都可为父进程所见
父进程将被阻塞,直到子进程调用execve()或exit() 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
int clone(int (*fn)(void *), void *child_stack, int clone_flag,
void *arg);
参数说明
fn:待执行的程序
child_stack:进程所使用的堆栈
clone_flag:由用户指定,可以是多个标志的组合
arg:执行fn所需的参数
功能
创建轻量级进程(LWP)的系统调用
通过clone_flag控制
8.进程、用户线程、内核线程的主要区别。
进程:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,被操作系统调度,一个系统资源的的集合。
用户线程:
存在于用户空间中,通过线程库来实现
线程创建和调度都在用户空间进行,以进程为单位调度
内核线程:
在内核空间内执行线程的创建、调度和管理
内核线程的创建和管理慢于用户线程的创建和管理
9、为何fork系统调用能返回两个不同的返回值。
第三讲:进程调度
1.Linux
2.4及2.6进程调度体系、调度框架的特点及差别。
Linux2.4的调度体系基于共享全局队列,其算法属于O(n),开销是线性增长的。
Linux2.6每个处理器都有独立的就绪进程队列,各个处理器可以并行运行调度程序来挑选进程运行,不同处理器上的进程可以完全并行地休眠、唤醒和上下文切换。
2.主动调度与被动调度的特点。
Linux2.4:
主动调度:直接调用schedule()
被动调度:置位当前进程的need_resched,和主动调度相比,被打调度有一定的调度延时Linux2.6:
包含了Linux 2.4的调度时机,增加内核可抢占。
3.Linux 2.4及2.6进程调度中优先级算法的设计。
优先级定义
·静态优先级:priority(0~70)
表示分配给进程的时间片
指明在被迫和其他进程竞争CPU之前,进程允许的最大时间片
只能由用户进行修改,不随时间而改变,一般通过nice设定
·动态优先级:counter
进程拥有CPU时随时间不断减小
指明在这个时间片中所剩余的时间量
当小于0时,标记进程重新调度
·实时优先级:rt_priority(1~99)
确定实时进程的调度顺序,较高权值进程优先于较低权值进程非实时进程的优先级为0,因此实时进程总优先于非实时进程
2.4:
普通进程
基本思想:动态优先级调度
·通过更新counter值,周期性修改进程优先级(避免饥饿)
基本过程
·counter变为0时,用priority对counter重新赋值
·所有可运行状态进程的时间片都用完后才对counter重新赋值
·进程运行过程中,counter的减小为其它进程提供运行机会
·该机制相当于优先级在动态变化,所以称之为动态优先调度
实时进程
基本思想:静态优先级策略
·counter只用来表示该进程的剩余时间片
·不作为衡量其是否值得运行的标准(与普通进程的区别)
调度设计的基本原则:
动态调整优先级及时间片长度
2.6:
·基于每个CPU分配时间片,取消全局同步和重算循环
每个处理器有两个数组:活动就绪进程队列和不活跃就绪进程队列
进程消耗完其“时间片”后,进入不活跃就绪进程数组中相应队列的队尾
当所有进程都“耗尽”其“时间片”后,交换活跃与不活跃就绪进程队列数组,不需要任何其他的开销
·每个数组中有140个就绪进程队列(runqueue),每个队列对应于140个优先级的一个
通过位图标记队列状态
调度时,通过find_first_bit()找到第一个非空的队列,并取队首进程
不管队列中有多少就绪进程,挑选就绪程的速度恒定,因此称为0(1)算法
4.Linux 2.4及2.6负载均衡机制的实现思路。
Linux2.4的负载平衡基本策略:进程p被切换下来之后,如果还有CPU空闲,或者该CPU上运行的进程优先级比自己低,那么p 就会被调度到那个CPU上运行,内核使用该办法来实现负载平衡。
Linux2.6的基本策略:采用相对集中的负载平衡方案,分为“推”和“拉”两类操作
“拉”操作:当某个CPU负载过轻、而另一CPU负载较重时,系统会从重载CPU上“拉”进程过来。
有两种调用方式:“忙平衡”:当前CPU不空闲;“空闲平衡”:当前CPU空闲。
“推”操作:在系统启动时自动加载(每个CPU一个),并将自己设为SCHED_FIFO的实时进程,定期检查migration_queue中是否有请求等待处理,若没有,就在TASK_INTERRUPTIBLE中休眠,直至被唤醒后再次检查。
5.Linux 2.6如何体现交互式进程优先的。
内核有四处对交互式进程的优先考虑
①sleep_avg
交互式进程因为休眠次数多、时间长,sleep_avg也会相对更大一些
②interactive_credit
记录进程的交互程度
判断进程是否是交互式进程
③TASK_INTERACTIVE()宏
④就绪等待时间的奖励
对交互式进程的优先级奖励
系统通过HIGH_CREDIT() 累积方式完成奖励
当进程从CPU切换下来时,如果是交互式进程,则它参与优先级计算的运行时间会比实际运行时间小,以此获得较高的优先级
交互式进程处于TASK_UNINTERRUPTIBLE状态下的休眠时间也会叠加到sleep_avg上,从而获得优先级奖励
6.内核抢占、用户抢占的实现机制及差异;何种情形下不允许内核抢占。
当进程位于内核空间时,有一个更高优先级的任务出现时,如果当前内核允许抢占,则可以将当前任务挂起,执行优先级更高的进程。
第四讲:进程通信
1.常用进程通信方式在设计目标、使用场景的主要区别及相关函数的使用方法。
信号(signal):进程或内核使用信号机制通知其他进程发生某一事件
管道(pipe)及有名管道(named pipe):用于具有亲缘关系的进程间通信
相关代码略(太多。
)
相关函数看ppt,看完估计想死的心也有了←_←
信号安装函数:signal(), sigaction()
信号发送函数:kill(), sigqueue(), raise(), alarm(), setitimer(), pause()
信号集操作函数:sigemptyset(), sigfillset(), sigaddset(), sigdelset(), sigismember() 。
2.可靠信号及非可靠信号的特点、主要区别,信号处理机制的内核实现机制。
不可靠信号
·信号值小于SIGRTMIN
·进程每次处理信号后,将信号响应函数设置为默认动作,需调用signal() 重新安装信号
·非实时信号都是不可靠信号,不支持排队,信号可能丢失
可靠信号
·信号值介于SIGRTMIN和SIGRTMAX之间
·新信号安装函数sigaction()和信号发送函数sigqueue()
·实时信号都是可靠信号,支持排队
3.IPC资源、IPC键、IPC标示符的定义。
IPC资源
表示单独的消息队列、共享内存或信号量集合。
IPC键
·IPC对象的外部表示,可由程序员选择。
·如果键是公用的,则系统中所有进程通过权限检查后,均可找到和访问相应IPC 对象。
·如果键是私有的,则键值为0。
(每个进程都可建立一个键值为IPC_PRIVAE的私有IPC对象。
)
IPC标识符
·由内核分配给IPC对象,在系统内部唯一
·IPC对象标识符的获取:XXXget()
①将IPC键传递给以sys_打头的内核函数,并为用户分配一个与IPC对象相对
应的数据结构。
②返回一个32位IPC标识符,进程使用此标识符对该资源进行访问
4.IPC资源内核结构设计的特点。
(真没理解,不知道对不对)
设计了:消息队列:(msgid_ds )16个。
共享内存:(shmid_ds )4096个。
信号量
(semid_ds):128个
5.不同IPC进程通信机制在内核结构设计上的异同点。
6.可撤销信号量的定义及其内核实现机制。
第五讲:系统调用与中断处理
1.系统调用与中断处理在内核实现机制上的异同点。
系统调用:
·位于用户空间进程和硬件设备之间的一个中间层
·为用户态进程与硬件设备交互提供一组接口
中断:异步的,来自处理器之外的中断信号,在程序执行的任何时候可能出现.
区别:a.中断允许嵌套发生,但异常多数情况为一重.
b①为用户空间提供一种硬件的抽象接口.
②是除异常和陷入外,用户空间访问内核的唯一入口.
③保证系统的稳定与安全.
2.封装例程的定义及作用。
定义:
系统调用可由用户态进程或内核线程使用,但内核线程不能使用库函数,为简化处理,linux 定义了七个内核封装宏。
作用:
·屏蔽底层复杂性
·将系统调用封装成应用程序可直接调用的函数(库函数)
3.系统调用的编写方法。
用户程序调用系统调用总控程序system_call
·系统调用总控程序入口地址system_call挂在中断0x80上
·用户程序执行int $0x80 实现“从用户程序到系统调用总控程序”的切换
·处理过程
在进程的内核态堆栈中保存大多数寄存器的内容
调用对应系统调用服务例程处理系统调用
通过ret_from_sys_call()从系统调用返回服务程序
·system_call通过“call * SYMBOL_NAME(sys_call_table)(,%eax,4)调用服务程序
调用形式
call * SYMBOL_NAME(sys_call_table)(, %eax, 4)
说明
eax保存相应系统调用编号
此编号对应系统调用服务例程在系统调用向量表sys_call_table中的编号
由于系统调用向量表sys_call_table每项占4个字节,所以由%eax 乘上4形成偏移地址sys_call_table为基址,基址加上偏移所指向的内容就是相应系统调用服务程序的入口地址sys_call_table
·记录已注册的系统调用列表
每个有效的系统调用指定一个唯一的系统调用号
·定义在/linux/include/asm/unistd.h中的entry.s段
sys_ni_syscal()系统调用
只返回-ENOSYS,专门针对无效的系统调用而设置
定义形式
asmlinkage int sys_ni_syscall(void) {
return -ENOSYS;
}
处理边界错误,0号系统调用就是用此特殊的服务程序
用于替换旧的、已淘汰的系统调用
用于将要扩展的系统调用
4.中断处理、异常及信号在实现机制、处理流程上的异同点。
5.Linux系统中如何实现IRQ共享的。
irqaction结构
作用
·包含内核接收到特定IRQ之后应采取的操作
·用来实现IRQ共享,维护共享IRQ的特定设备和特定中断(所有共享同一IRQ的中断服务例程链接在一个action表)
参数说明
flags:描述IRQ和I/O设备之间的关系
·SA_INTERRUPT:快速中断处理程序(在本地处理器上禁止所有中断的情况下执行)
·SA_SAMPLE_RANDOM:中断是源于物理随机性的
·SA_SHIRQ:此IRQ与其它struct irqaction共享
mask:中断屏蔽字(未使用)
name:产生中断的I/O设备名
dev_id:标识I/O设备的一个唯一的ID
·Linux支持的所有硬件设备的每一种类型,都有一个由制造厂商定义的在此成员中记录的设备ID
next:指向下一个irqaction
·如果IRQ被共享,则指向队列中下一个struct irqaction
6.保护模式与实模式的定义。
从80386开始,cpu的工作模式。
在实模式下只能访问1M以下的内存,而在保护模式下可寻址超过4G字节的物理地址空间。
7.下半部分处理的定义。
执行与中断处理密切相关但中断处理程序本身不执行的工作
执行期间可以响应中断
8.Linux下半部分处理的实现方式及不同实现方式之间的异同点、关联关系;
具体代码看ppt)
①BH机制
·最早的“下半部”实现机制——“bottom half”
(提供了一种静态创建、由32个“bottom half”组成的链表。
处理函数必须在编译时就定义好。
上半部分通过一个32位整数中的一位来标识可执行的“bottom half”。
每个BH都在全局范围内同步,不允许任何两个BH同时执行(即使在不同CPU 上)。
)
②软中断
·一组静态定义的下半部接口
(有32个,必须在编译阶段静态注册
可以在所有处理器上同时执行(即使两个类型相同的软中断)
一个软中断不会抢占另一个软中断
软中断处理过程中允许响应中断,但自己不能休眠
在一个处理程序运行的时候,当前处理器上的软中断被禁止)
③Tasklet
·基于软中断实现、灵活性强、动态创建
(类型相同的tasklet不能同时执行。
两种不同类型的tasklet可以在不同处理器上同时执行。
tasklet由HI_SOFTIRQ及TASKLET_SOFTIRQ两类软中断代表组成,前者的优先级高于后者。
)
tasklet与软中断的权衡
通常应该使用tasklet
软中断适用于执行频率很高且连续性要求很高的情况
④工作队列
·将工作推后,交由一个内核线程去执行
下半部分在进程上下文执行,通过工作队列执行的代码可以占尽进程上下文的所有优势a支持使用大容量内存
b支持获取信号量
c支持执行阻塞式I/O操作
工作队列可以用内核线程替换,但一般不建议单独建立对应的内核线程小结比较工作队列vs.软中断/tasklet
①工作队列支持睡眠,软中断/tasklet不支持
②若需要使用一个可以重新调度的实体来执行下半部分处理,则应该使用工作队列
9.软中断的调度特点。
·有32个,必须在编译阶段静态注册
·可以在所有处理器上同时执行(即使两个类型相同的软中断)
·一个软中断不会抢占另一个软中断
·软中断处理过程中允许响应中断,但自己不能休眠
第六讲:内存寻址与管理
1.逻辑地址、线性地址、物理地址的定义及转换过程及计算方法。
●逻辑地址:每个逻辑地址由一个段(segment)和偏移量(offset)组成
●线性地址:32位无符号整数,可表示4G地址空间
●物理地址:用于芯片级内存单元寻址,与从CPU的地址引脚发送到内存总线上的电信号相对
应
●转换过程:内存控制单元(MMU)通过分段单元(segmentation unit)将逻辑地址转换成
线性地址,分页单元(paging unit)将线性地址转换成一个物理地址
计算例题:
2.常规分页机制、物理地址扩展的实现方法。
常规分页
①从i386起,Intel处理器的分页单元处理4KB的页
②32位线性地址被分成3个域
·目录(directory)
最高10位,决定页目录项(指向适当的页表)
·页表(table)
中间10位,决定页表项(指向所在页框的物理地址)·偏移量(offset)
最低的12位,决定页框内的相对位置
③线性地址的转换(二级模式)
·分两步完成,每一步都基于转换表
第一种称为页目录表(page directory)
第二种称为页表(page table)
·正在使用的页目录表的物理地址存放在CPU的CR3寄存器中
(每个页目录项4字节,最多1024项
页表地址的低12位总为0,所以用高20位指出32位页表地址即可)
物理地址扩展(PAE)分页(背景)
a由于用户线程地址空间需要,内核不能直接对1G以上的RAM进行寻址
大型服务器应用常需要大于4GB的空间。
b.Intel的修正途径
在Pentium Pro体系结构,地址线36位,寻址能力提升到236=64GB
物理地址扩展(PAE)分页机制
①分页方法
·64GB的RAM分成224个页框,页表项的物理地址字段从20位扩展到24位页表项大小从32位(4字节)变成64位(8个字节),一个4KB的页表包含512个表项
·引入页目录指针表(Page Directory Pointer Table, PDPT)的页表新级别由4个64位表项组成
CR3控制寄存器存放PDPT的基地址段
②启动方法
·设置CR4控制寄存器中的PAE 标志激活
·页目录项中的PS 标志启动大尺寸页
3.段选择子的结构。
逻辑地址=段:段内偏移
段标志符:16位长,称为段选择子
段内偏移:32位长
使用16位段寄存器来指明当前所使用的段
索引号
13位,指定GDT/LDT 表中相应的段描述符
TI(Table Indicator)
1位,指明段描述符在GDT (TI=0)或LDT (TI=1)中
RPL(Request Privilege Level)
2位,当相应段选择符装入到cs 寄存器中时,指明CPU 的当前特权级(用户/内核)
4.伙伴系统的定义及算法执行机制。
索引号
TI RPL 3 2 1 0
15 段选择子格式
伙伴的必要条件
·大小相同
·物理地址连续
·假定伙伴的大小为2k,第一个伙伴的第一个页框的物理地址必须是2×k×4KB的倍数
事实上伙伴是通过对大块的物理内存划分获得的
·假如从第0个页面开始到第3个页面结束的内存
·每次都对半划分,那么第一次划分获得大小为2页的伙伴,进一步划分,可以获得大小为1页的伙伴,例如0和1,2和3。