什么是操作系统
没有清晰的定义,主要实现2个功能:
○1管理,支持应用软件,○2调用分配资源
层次在硬件之上,应用程序之下。
Shell linux,windows,android的界面 如gui
Kernel 内核 是操作系统的重点,功能包括4部分:
CPU(CPU调度,进程,线程管理)
内存(物理内存,虚拟内存)
文件 disk(磁盘块),较为底层,抽象为文件系统 (文件系统管理)
中断处理和外设设备驱动
Kernel 的特征:
- 并发:多个运行的程序需要OS管理和调度
—并发:在一段时间内有多个程序可以运行
并行:在一个时间点上有多个程序 需要有多个cpu - 共享:分时,互斥共享,同时对一个资源只有一个程序可以访问,但可以通过隔离成两块,达到“同时”访问
- 虚拟:操作系统面对的是硬件。将CPU虚拟化成进程,磁盘虚拟化成文件,内存—>虚拟空间,每个应用程序/用户觉得有一个计算机专门为他服务
- 异步:一个CPU的情况下,只能有一个程序在跑,程序的执行不是一贯到底,而是走走停停,但只要运行环境相同,OS保证程序运行的结果相同。
操作系统实例
Unix家族 UNIX BSD(伯克利软件发行版) 写C的那俩
BSD由伯克利在UNIX基础上改编,尤其网络协议方面有独到之处。
开源,产业界。惠普,苹果
linux家族 一个学生搞出来的 红帽子,deforo ,suse
安卓终端是linux内核,移动端占据最多
dos-> windows家族 桌面龙头 服务器和终端是linux最大
用户友好
linux启动过程
按下电源按钮的直到欢迎页出来之后,linux总共做的事可以分为五步来完成。
1、 BIOS加电自检:
加电自检,检测硬件设备。然后按照cmos上面的顺序来搜索处在活动状态下的可以引导的设备。可以是光驱、软盘、USB等。
2、 加载主引导加载程序(MBR):
主引导程序是一个512字节的映像。包含一点机器码还有一个小的分区。
主引导程序的任务就是查找并且加载处在硬盘分区上的次引导程序。通过分区表查找活动分区,并将处在活动分区的次引导加载程序读取到内存里面运行。
3、 加载次引导记载程序(GRUB)
次引导加载程序只要就是加载linux内核。
上一阶段结束之后次引导加载程序就会在内存里面跑起来。就会出现GRUB图形界面,让用户选择加载什么样的内核。
4、 linux内核映像:
用户选择要加载的内核之后,次引导加载程序(GRUB)就会根据/boot/grub.conf配置文件中所设置的信息,从/boot/所在的分区上读取Linux内核映像,然后把内核映像加载到内存中并把控制权交给Linux内核。
linux内核获得控制权之后开始干自己的事
1、 检测硬件
2、 解压缩自己并安装必要驱动
3、 初始化与文件系统相关的虚拟设备,LVM或RAID
4、 装载根文件系统,挂在根目录下面
5、 完成之后,linux在进程空间里面加载init程序,下面轮到init干活
5、 init进程
init是所有进程的发起者和控制者,所有的进程都由此衍生。
init进程获得控制权之后,它会执行/etc/rc.d/rc.sysinit脚本,根据里面的代码设置环境变量、网络、启动swap、检查并挂载文件系统、执行其他初始化工作。
至此,linux启动完成。
我们稍微总结一下:
首先是BIOS加电自检,之后加载主引导加载程序、次引导加载程序,最后就是linux内核映像,完了把控制权交给init进程,完成初始化工作。
swap分区是什么?
类似windows系统中的虚拟内存,当物理内存不够用的时候,使用swap中的内存。
操作系统的中断、异常和系统调用
三者差异:
1. 源头不一样,网卡声卡显卡等等产生事件—中断;APP意想不到的行为—异常;APP主动请求OS提供服务—系统调用
2. 处理时间不一样。中断:异步;异常:同步;系统调用:同步或异步
异步的含义:当一个事件发生时,APP并不知道它什么时候会发生
异常和系统调用都是一个特定指令触发了事件,同步时间点。
系统调用也有可能异步,当发出请求后返回的时间是异步的。如果APP在发出请求后没有等待,而是干别的去了,返回点是异步的。而请求的点是同步的。
3.响应状态
中断:持续,app对用户是透明的,感觉不到
异常:杀死或重新执行APP的异常指令,也透明
系统调用:等待和持续,不会重复执行
中断和异常的处理机制
中断—-
硬件:设置中断标记(cpu初始化),CPU看到具体的中断事件的ID中断号(程序访问的中断向量地址),根据中断表,访问一些为该事件服务的功能,跳到对应地址。
软件:OS要保存当前程序处理状态,中断服务程序处理(根据具体的时间ID对应功能/地址),清除中断标记,恢复之前保存的处理状态(应用程序是不知道的,是透明的)
异常——
异常编号,OS会保存现场,异常处理(杀死程序or OS修复程序需要的服务后重新执行异常指令),恢复现场。应用程序不知道在执行到特定指令后会产生异常,也是透明的。
系统调用——
应用程序调用printf时会触发系统调用write(),OS再去访问对应的外设。执行后OS返回一个成功或者失败。程序访问主要是通过高层的API接口而不是直接系统调用。常用的有:
Win32 API
POSIX API 通用可移植 linux unix mac os x
最底层就是win32 or posix 定义了操作系统到底能提供哪些系统调用
JAVA API 用于JAVA虚拟机(JVM)
操作系统对内存分配做了什么:
(1)抽象,逻辑地址空间;(2)保护,独立地址空间;(3)共享,访问相同内存;(4)虚拟化,更多的地址空间,对应用程序透明
操作系统管理内存的不同机制:
程序重定位,分段,分页,虚拟内存,按需分页虚拟内存
OS本身也是软件,实现高度依赖于硬件,要知道内存架构,MMU(内存管理单元,硬件组件中负责处理CPU的内存访问请求)
连续内存分配:内存碎片与分区的动态分配
物理内存分配可以分为连续分配和非连续分配。
连续分配会造成内存碎片问题,空闲内存不能被利用,外部碎片,在分配单元见的未使用内存,内部碎片,在分配单元中的未使用内存。
简单的内存管理方法:
当程序从硬盘加载到内存中时,要分配一个连续的区间;当应用程序需要访问数据时,要空间。
OS要跟踪。。。满块,空快(孔洞)
分配策略(貌似严蔚敏的数据结构课讲过?): 首次适配,最有适配,最差适配
1. 首次适配,从0地址往后查找和使用第一个可用空闲快(要比需要的空间大)。基本实现机制要求把空闲的内存块按地址排序。回收要考虑能否合并内存块。
优点:简单,易于产生更大的空闲快,向着地址空间的结尾
劣势:易产生外部碎片(随着动态分配加剧),不确定性
2. 最优适配:找比需求大但最接近需求的空闲内存块,产生尽可能小的内存碎片。原理是为了避免分配大空闲块,最小化外部碎片,要求对空闲地址快按尺寸size排序,回收要合并。
优点:当大部分分配需要小空间时使用,简单
缺点:外部碎片太小太细,不利于后续重分配。
3. WORSTFIT 最差匹配
使用最大的空闲快,大块拆分变小块,可以避免产生太多微小的碎片,也要排序,回收合并。
优势:分配中大型SIZE时实用
缺点:重分配慢,对大块的请求可能没得用了。
非连续内存分配:分段、分页
为什么需要非连续内存分配?
连续内存分配有碎片的缺点,对应非连续的优点:更好的内存利用和管理,允许共享代码和数据(共享库。。),支持动态加载和动态链接。最大的问题在于管理的开销。在虚拟地址和物理地址之间的转换,如果用软件来实现,开销巨大。因此要考虑用硬件来协同解决。
管理方法?
分段,分页机制,更好的分离和共享
分段机制:程序的分段地址空间设计,寻址方案。
把逻辑地址空间分散到多个物理地址空间,堆-→堆,运行栈-→运行栈,程序数据-→数据,运行exe—>代码和库
寻址方案:
一维连续逻辑地址,把一个段看成一个内存块。程序访问内存地址分为两部分,段的寻址(段号segment number)+ 段内偏移的寻址(addr)
段寄存器+地址寄存器实现方案(x86)
单地址实现方案(s+addr合在一起)
分段和分页
打个比方,比如说你去听课,带了一个纸质笔记本做笔记。笔记本有100张纸,课程有语文、数学、英语三门,对于这个笔记本的使用,为了便于以后复习方便,你可以有两种选择。
第一种是,你从本子的第一张纸开始用,并且事先在本子上做划分:第2张到第30张纸记语文笔记,第31到60张纸记数学笔记,第61到100张纸记英语笔记,最后在第一张纸做个列表,记录着三门笔记各自的范围。这就是分段管理,第一张纸叫段表。
第二种是,你从第二张纸开始做笔记,各种课的笔记是连在一起的:第2张纸是数学,第3张是语文,第4张英语……最后呢,你在第一张纸做了一个目录,记录着语文笔记在第3、7、14、15张纸……,数学笔记在第2、6、8、9、11……,英语笔记在第4、5、12……。这就是分页管理,第一张纸叫页表。你要复习哪一门课,就到页表里查寻相关的纸的编号,然后翻到那一页去复习
两者的优缺点:
在段式存储管理中,将程序的地址空间划分为若干段(segment),如代码段,数据段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)
在页式存储管理中,将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的页框,程序加载时,可以将任意一页放入内存中任意一个页框,这些页框不必连续,从而实现了离散分离。页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)
两者的不同点:
(1) 分页仅仅是由于系统管理的需要而不是用户的需要。段则是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好地满足用户的需要。
(2) 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。
(3) 分页的作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个记忆符,即可表示一个地址;而分段的作业地址空间则是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
页表
进程运行的时候操作系统会自动进行映射。操作系统是怎么做到的呢?实际上操作系统为每一个进程维护了一个从虚拟地址到物理地址的映射关系的数据结构,叫页表,页表的内容就是该进程的虚拟地址到物理地址的一个映射。
在分页机制,X86使用了四种数据结构:
· 页目录项(PDE,Page Directory Entry):32bits结构,高20bits为页表基地址(物理地址),以4KB为递增单位,低12bits为页表属性,具体换算参见后面初始化部分;
· 页目录(Page directory):存储页目录项,位于一页中,总共可容纳1024个页目录项;
· 页表项(PTE,Page Table Entry):32bits结构,高20bits为页基地址(物理地址),低12bits为页属性;
· 页表(Page table):存储页表项,位于一页中,总共可容纳1024个页表项;
· 页(Page):4KB的连续地址空间;
操作系统的内容分为几块?什么叫做虚拟内存?他和主存的关系如何?内存管理属于操作系统的内容吗?
操作系统的主要组成部分:进程和线程的管理,存储管理,设备管理,文件管理。
虚拟内存是一些系统页文件,存放在磁盘上,每个系统页文件大小为4K,物 理内存也被分页,每个页大小也为4K,这样虚拟页文件和物理内存页就可以对应,实际上虚拟内存就是用于物理内存的临时存放的磁盘空间。页文件就是内存页, 物理内存中每页叫物理页,磁盘上的页文件叫虚拟页,物理页+虚拟页就是系统所有使用的页文件的总和。
请求分页存储管理方式
请求页表机制:作用是把用户的逻辑地址映射为内存空间中的物理地址。
虚拟存储器页面置换算法
1:最佳置换算法(Optimal):一种理论的算法,选着淘汰的页面是以后一定不再使用的页面(理想化的),该算法无法实现,只能作为其他算法好坏的一个评价对比。
2:先进先出(FIFO)算法:总是最先淘汰最先进去的页面,该算法容易实现。缺点:通常程序调入内存的先后顺序和程序执行的先后顺序不一致,导致缺页率高。
3:最近最久未使用(LEU):FIFO算法性能差,LRU算法根据页面调入内存的先后孙旭决定,因为违法预测未来的使用情况,就是用过去的使用情况作为将来的使用情况的近似。
4:最少使用算法(LFU):在每个页面设置一个移位寄存器记录该页面的访问频率,最近时期最少使用的页面被淘汰