嵌入式操作系统概述
工作在嵌入式环境中的操作系统 Embedded Operating System。
嵌入式和一般操作系统区别:
- 非通用操作系统,用于完成特定功能;
- 性能实时性能源可靠性要求高;
- 占用资源少;
- 可剪裁,可配置。
OS 主要功能:任务管理,(内存)存储管理,IO 管理,文件管理(当然这4个功能也可能被裁剪掉)。
有可能考察哪些 OS 是嵌入式 OS。
对响应时间的敏感度又可以分为:硬实时(不接受规定响应时间后的响应。如果没及时收到响应可能产生严重错误),软实时(可以接受一定程度迟到的代价)和非实时系统。
按软件体系结构分为单体结构(uC/OS),分层结构(MS-DOS),微内核结构(VxWorks)。
单体结构:中间件和驱动程序都集成在内核里,系统只有一个可执行文件,如 linux,uc/OS. 性能较好,模块间相互调用通信方便,但是操作系统体积大,裁剪困难。
分层结构:内核分了许多层,上一层只能调用下一层。下一层提供 API 给上层。
系统开发维护相对简单,但是开发 API 开销增加。
API 就是一些定义的 .h 文件。
微内核结构:内核尽可能缩减,进程服务、文件服务、内存服务等都放在用户态而不是核心态,核心态只放微内核、设备驱动程序、硬件。
比如应用程序启动进程,发送请求给微内核,微内核发送请求给进程服务,进程服务处理后返回给微内核,微内核返回给应用程序。
易拓展,易移植,安全性高,但是速度慢,切换回增加开销,且对微内核性能要求高。
进程管理
系统进行资源分配和调度的独立单位。由程序块,进程控制块(PCB),数据块组成。
现代操作系统:CPU 是厨师,程序是食谱,进程是烹饪的过程,是动态的。
进程是系统资源分配和调度的单位。
三态模型:就绪,运行,阻塞。就绪态准备好运行但是没有空闲 CPU,还不能运行;运行态正在占用 CPU 运行;阻塞态在等待一些事件(如 IO 设备)。三态模型可见:
操作系统学习笔记_2 中断和系统调用;进程和线程_中断和系统调用的区别_灰海宽松的博客-CSDN博客
五态模型:运行,活跃就绪,静止就绪,活跃阻塞,静止阻塞。
挂起:调出内存,保存到外存队列中,并释放资源。
激活:调入内存。
挂起可以释放进程占用的资源。比如内存不够的时候。
前趋图
图2:A入度0,出度1,说明一开始就能执行。
D入度3,出度1,说明需要先做3个任务才能轮到D。
同步和互斥
同步:直接的制约,需要有顺序,比如先切肉再下锅。
互斥:间接制约,比如大家一起过独木桥,一个人过的时候别人不能过。
同步的典型例子:生产者消费者。详细介绍,临界资源和临界区,和一些其他进程关系可见:
操作系统学习笔记_2 中断和系统调用;进程和线程_中断和系统调用的区别_灰海宽松的博客-CSDN博客
信号量 P:申请。V:释放。
P:先S–,然后看S是否<0.如果<0说明没有足够的资源,阻塞。否则进程执行。
V:S++,如果S<=0则进程执行。否则说明没有进程要用资源,现在处于空闲阶段。
s1:空闲缓冲区,初值=1.
s2:非空缓冲区,初值=0.
死锁
四大条件,预防方法:
操作系统学习笔记_3 管程;死锁;内存_灰海宽松的博客-CSDN博客
主要讲的就是有序资源分配和银行家算法。
银行家算法主要就是看一个进程最多还需要的资源与剩余资源总量相比,如果小于剩余资源总量则可以分配。
现有:2,1,0。
进程 | 还需要 |
---|---|
P1 | 5,3,1 |
P2 | 0,1,0 |
P3 | 6,0,1 |
P4 | 0,0,1 |
P5 | 2,3,1 |
可知唯一的安全序列是B。
任务调度
调度时机,调度方式,调度算法。
操作系统学习笔记_2 中断和系统调用;进程和线程_中断和系统调用的区别_灰海宽松的博客-CSDN博客
任务调度是一个函数,需要调度的时候执行一下。比如把任务从就绪态调度到运行态。
何时调度?有任务运行结束时,因IO堵塞时,IO完成时,中断发生或者时间片用完时,创建新任务时。
调度方式不可抢占和课抢占。
可重入函数:可以被中断等打断。抢占式内核必须用可重入函数。
性能指标还有调度开销(调度的时空开销),公平性(任务得到的 CPU 时间应该大致相同),均衡性(系统各个部分都尽量忙起来)。性能指标之间其实是相互冲突的,因此也要考虑一下不同指标之间的优先级。
任务间通信
低级:信号量。
高级:共享内存,消息传递,管道。
存储管理
内存
分区
以前:单一连续分配,内存不分区,一次只能执行一个任务。
固定分区分配:给定分区,不方便。
可变分区分配:按作业大小分配分区,释放分区时分区和临近分区合并。
页式存储管理:比如我们程序有300K,但是内存一共大小才150K,整个程序拿不进去。我们可以把程序分页,比如150个2K页,然后每次按照执行顺序拿几页进去执行。
第几页对应内存的哪个位置,需要有一个页表来存储。有页号和块号。
用户的页:是逻辑地址,页号+页内地址。页号标识了一共有多少页,页内地址标识了每个页的最大大小。
逻辑地址转物理地址:页号根据页表寄存器找页表位置,找到页表中页号对应的块号,块号和页内地址再找到物理地址。
利用率高,碎片小,分配管理简单;但是系统调整开销大,可能发生抖动(反复调入调出)。
例题:
前两位:页号,变为物理块号。
后面的部分是页内地址,不变拼接。
页面大小4K=2^12,也是指明页内地址是12位。
也就是8644/2^12,前面的部分进行页号和物理块号的转变,取余的部分原封不动的拼接。
段式存储
段式存储也包含段号和段内地址,和页式存储不同的地方在于每页大小不固定,而是动态分配。
优点:1. 多道程序可以共享一段内存,比如一个函数申请了一块内存,所有程序调用的时候都可以访问内存中这个函数而不用把函数重复放入内存。
寻址方式和页也很像,是用段号去段表中找出对应的段长和基址,基址~基址+段长的范围就是这个段的内存空间。
缺点在于内存利用率不高,可能有外部碎片((1条消息) 操作系统学习笔记_3 管程;死锁;内存_灰海宽松的博客-CSDN博客)
段页式存储
一个程序一个段,段内又分几个页在不同的地方存储,可以更有效利用碎片化空间。
逻辑地址包含:段号,页号,页内地址。
段号可以找到页长和页基址,页长和页号校验看是否越界。不越界则根据页基址和页号找到某一页的内存块号,再加上页内地址求得我们要访问的物理地址。
缺点在于开销大,管理麻烦。
虚拟存储
((1条消息) 操作系统学习笔记_3 管程;死锁;内存_灰海宽松的博客-CSDN博客)
上面的方法都是整个程序放入内存,虚拟存储是把一个程序分多次装入,每次要访问一段时看内存里有没有,没有从外存调入内存;如果内存已满,还需要根据页面置换算法挑一个页面换出内存。
四大置换算法:OPT 最佳置换算法(未卜先知,能知道哪个将来最晚才用,把那个页面换了),FIFIO 算法,LRU 最近最少未使用置换算法(把最近没用过的换出去),CLOCK 最近未用置换算法(每个程序弄一个计数器,访问过一次++,把计数器最小的换出去)。
例:
023最近都访问过,只有3没修改过。如果把02换出去还要写回内存,所以换3开销最小。
磁盘
调度算法:要访问磁盘上多个文件的顺序。
FCFS:不必多说。
SSTF 最短寻道时间优先:优先访问离当前磁头最近的文件。
SCAN 扫描算法:优先沿当前方向扫描到磁盘结尾或开头,然后再按反方向访问。
CSCAN 循环扫描算法:访问到开头/结尾后,可以再跳到结尾/开头进行访问。
读取磁盘数据的时间包括:1. 找磁道的时间;2. 找块/扇区的旋转延迟时间;3、 传输时间。
找磁道:平均10*10=100ms;
旋转延迟时间:100ms;
传输时间:2ms;
202*100=20200ms。
非格式化容量:容量=面数 * (磁道数/面) * 内圈周长 * 最大位密度
格式化容量:容量=面数 * (磁道数/面)* (扇区数/道) *(字节数/扇区)
首先,磁盘哪怕系统还在处理记录时也还在旋转。
因此R0读取3s,处理R0 3s,这时指针已经走到R1了。
最长时间:R0是3+3s,R1需要转一圈回来,30+3+3s,R2也需要转一圈……时长为(36)*10+6=366s。
优化分布存储后,则每次指针都刚好指在读取开头,(3+3)*11=66s.
文件管理
索引文件的管理
顺序结构:连续的存储,适用于一次性的存储。
链接结构:每个存储块里存储了下一块的地址。
索引结构:一个索引表,里面每个索引指向一个物理块。如果不够,最后几个索引再指向下一个索引表。
树型目录结构
树型结构:linux 里的结构,注意绝对路径和相对路径的区分。
空闲存储区管理
位示图法:类似买电影票,一眼就能看到哪些座位空闲哪些不空闲。
设备管理
虚设备与SPOOLING技术
输出井,把输入数据放入内存中的预输入缓冲区,输出数据放到缓输出缓冲区。井管理程序可以进行两者间的通信。
比如四个用户同时给打印机发请求,打印信息都放到预输入程序中,打印机自己调度打印。不仅提高了 IO 速度,而且每个用户都感觉打印机在为自己所用。