操作系统
历史
- 无操作系统 : 1946年~1950年代末期:第1代计算机,硬件以电子管为主,无操作系统。使用纸带传输程序和数据,操作系统只起加载作用。
- 批处理操作系统 :1960年代初期~1960年代中期:第2代计算机,硬件主要是晶体管,出现了以监督程序(monitor)为代表的批处理系统。
- 多道程序系统 : 1960年代后期~1970年代中期:第3代计算机,集成电路成为硬件的主流,产生了以多道程序系统为代表的通用操作系统。
- 现在操作系统 : 1970年代后期~现在:第4代计算机,大规模集成电路和超大规模集成电路是硬件的主流,分时系统、实时系统、嵌入式系统、网络操作系统、移动操作系统等适应不同应用场景的操作系统相继涌现。
定义
操作系统,管理硬件资源,提供接口给用户
资源
-
CPU(时间)->进程 CPU调度
内存(空间)->地址 物理内存/虚拟内存
-
磁盘->文件 文件系统
-
其他->中断处理/设备驱动
接口
命令接口
命令解释器shell连接了用户和内核,分为下面两种
- CLI shell(Command Line Interface shell )命令行界面
- GUI shell(Graphical User Interface shell )图形界面
system call
即系统调用,当应用程序需要执行特权操作(如文件操作、内存分配、进程管理等)时,它不能直接访问硬件或内核资源,而必须通过系统调用请求操作系统提供这些服务。是系统的底层接口
api
封装了系统调用,提供了更易用的功能
传参方法
- 参数少时寄存器,windows
- 参数多时内存 linux,solaris
- 栈
结构
层次式结构
单向调用,结构清晰
对层的详细定义很麻烦
微内核
保留基本功能在内核
- 低级存储管理
- 进程间通信(IPC)
- I/O和中断管理
但需要频繁切换核心态和用户态
模块化结构
利用面向对象来生成模块化的内核,全称为动态可加载模块化结构,linux
单个模块会导致系统崩溃,需要管理模块之间的依赖关系
虚拟机
虚拟机(Virtual Machine)指通过软件模拟的、具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统
虚拟机监视器(VMM),将单独的机器接口转换为多个虚拟的副本,虚拟机运行着完整的操作系统
原语
特点
**原语(Primitive)**是操作系统中的一种基本概念,指的是不可再分割的基本操作或指令。这些操作是系统提供的基本功能,通常由硬件支持或由操作系统实现,具有以下几个重要特性:
- 不可中断性(Atomicity):原语操作在执行过程中不能被打断,要么完全执行完毕,要么不执行。这意味着原语操作是原子的,其执行过程不可分割。在并发操作的环境下,原语能够保证操作的完整性和一致性。
- 基本操作:原语通常是操作系统提供的基础操作,是实现更复杂操作和功能的构建块。例如,在进程同步、进程通信等方面,操作系统会提供一些原语来确保系统的正确性和效率。
- 用于构建更复杂操作:原语通常是更高层次功能的组成部分,可以通过组合多个原语来实现复杂的任务。例如,通过使用
lock
和unlock
原语来实现互斥锁,确保同一时刻只有一个线程能够访问共享资源。
示例
基于linux
进程控制
这些原语用于创建、终止和管理进程。常见的进程控制原语包括:
- fork():创建一个新进程。新进程是调用进程的副本,但两个进程从此刻起独立运行。
- exec():用于加载并执行新的程序,通常与 fork() 结合使用来启动新程序。
- exit():终止当前进程,并向其父进程返回一个状态值。
- wait() 和 waitpid():父进程用来等待子进程结束,并获取子进程的退出状态。
- clone():类似于 fork(),但提供了更多的灵活性,允许创建线程或轻量级进程。
进程通信
这些原语用于进程间通信(IPC),以实现不同进程之间的数据交换和同步。常见的通信原语包括:
- pipe():创建一个管道,用于同一进程内的函数之间或父子进程之间的单向通信。
- socketpair():创建一对相互连接的套接字,适用于进程间的双向通信。
- message queue (msgget, msgsnd, msgrcv):消息队列是一种进程间通信方式,允许进程发送和接收固定大小的消息。
- semaphore (semget, semop, semctl):信号量用于进程间的同步,确保多个进程不会同时访问共享资源。
- shared memory (shmget, shmat, shmctl):共享内存允许多个进程直接读写同一块内存区域,是最快速的IPC机制之一。
- signal (kill, sigaction, pause, etc.):信号是异步通知机制,用于进程间的通知或中断处理。
文件系统
这些原语用于文件和目录的操作,以及文件系统的管理和维护。常见的文件系统原语包括:
- open():打开文件或设备,返回一个文件描述符。
- close():关闭由文件描述符标识的文件或设备。
- read() 和 write():从文件或设备读取数据或将数据写入文件或设备。
- lseek():改变文件指针的位置,用于随机访问文件。
- stat(), fstat(), lstat():获取文件的状态信息,如文件大小、所有者、权限等。
- unlink() 和 link():删除文件链接或创建硬链接。
- mkdir() 和 rmdir():创建或删除目录。
- rename():重命名文件或目录。
内存管理
这些原语用于管理进程的虚拟内存,包括分配、释放和保护内存区域。常见的内存管理原语包括:
- mmap() 和 munmap():将文件或设备映射到进程的地址空间,或解除映射。
- brk() 和 sbrk():调整进程的数据段边界,用于动态内存分配。
- malloc(), free(), calloc(), realloc():虽然这些不是系统调用,而是库函数,但它们基于底层的内存管理原语实现了动态内存分配。
设备管理
这些原语用于与硬件设备进行交互,包括输入输出操作和设备配置。常见的设备管理原语包括:
- ioctl():对特定设备进行控制操作,如设置终端参数、磁盘格式化等。
- select() 和 poll():监视多个文件描述符,等待其中任何一个变为可读、可写或发生异常条件。
- readv() 和 writev():从多个缓冲区读取数据或将数据写入多个缓冲区,常用于高效地处理分散/聚集I/O。
系统信息和控制
这些原语用于获取系统的状态信息或控制系统的行为。常见的系统信息和控制原语包括:
- uname():获取当前操作系统的名称和其他相关信息。
- sysinfo():获取系统的统计信息,如内存使用情况、负载平均值等。
- reboot():重启或关闭系统。
- setuid(), setgid(), seteuid(), setegid():更改进程的有效用户ID或组ID,用于特权提升或降权。
机制与策略
区别对待机制(mechanism)和策略(policy)是操作系统设计的一种非常有效的思路。
大部分的编程问题都可以被切割成两个部分:
机制决定如何做(how),而策略决定做什么(what)
进程
进程是系统分配资源和调度的基本单位
进程管理负责处理进程的创建、调度、终止、同步和通信。
PCB
描述进程的数据结构:进程控制块(Process ControlBlock,PCB),分为以下三个部分
进程标识
- 进程标识符(PID)
- 父进程标识符(PPID)
- 用户标识符(UID)
上下文
处理机状态信息保存区,用于保存进程的运行现场信息,以便进程从中断或调度时能够恢复执行。
- 用户可见寄存器:
- 存储用户程序可以使用的寄存器,如数据寄存器、地址寄存器等。
- 控制和状态寄存器:
- 程序计数器(PC):指示下一条将要执行的指令的位置。
- 程序状态字(PSW):保存进程的状态信息,如进程当前的执行状态(运行、等待等)以及中断标志等。
- 栈指针:
- 用于指示当前进程的栈顶,栈用于存储函数调用的返回地址、局部变量等。栈指针在进行过程调用、系统调用或中断处理时起到关键作用。
进程控制信息
这些信息用于操作系统内部的进程管理和调度。
- 调度和状态信息:
- 进程状态:指示进程当前的状态(如就绪、运行、等待、终止等)。
- 调度信息:帮助操作系统决定进程何时获得CPU时间(如优先级、时间片等)。
- 进程间通信信息:
- 包括进程间通信所需的各种标识、信号、信件等。这些信息用于支持进程间的同步、通信和数据交换。一般存储在接收方的PCB中。
- 存储管理信息:
- 包含指向进程映像(包括代码段、数据段、堆栈段等)的指针或数据结构,用于操作系统管理进程的内存。
- 进程所用资源:
- 记录进程打开、使用的系统资源,如打开的文件、设备句柄等。用于确保资源的正确释放和访问控制。
- 有关数据结构连接信息:
- 进程可以连接到一个进程队列中,或者通过某些机制(如父子进程关系、等待队列等)与其他进程的PCB建立联系。
五状态转移
七状态转移图 : 对就绪态和阻塞态增加了挂起(Suspense) 和解挂(Activate)
进程挂起 : 当内存不足时,将进程映像放在硬盘里,当需要使用时,解挂进程
线程
当需要进行加载资源之类的,出现了阻塞,这时候应该使用线程,让其独立于主线程之外加载
进程用于管理资源,而线程用于实际工作
线程池
减少创建销毁的系统开销
协程
协程(Coroutine)是一种轻量级的线程,允许程序在执行过程中切换任务。与传统的线程不同,协程并不需要操作系统的调度,它们在单个线程中通过手动切换来实现并发。
对于异步操作并不需要另外起线程,而是直接async/await
对于IO密集型的前端经常使用
进程同步
机制与策略
进程同步机制
- 信号量(Semaphore):用于协调进程之间的同步,保证多个进程访问共享资源时不会发生冲突,
wait()
和signal()
。 - 互斥锁(Mutex):一种特殊的信号量,保证临界区内的资源只被一个进程访问,使用P(),释放V()。
- 条件变量:用于在进程间传递状态信息,例如一个进程等待某个条件成立后才继续执行。
进程同步策略
- 临界区管理:通过使用互斥锁、信号量等同步机制,操作系统决定了进程如何访问共享资源,避免竞态条件。
- 死锁避免策略:如银行家算法,用于在多个进程之间协调资源分配,避免死锁的发生。
死锁
互相持有对方等待的资源,但同时又还需要继续使用已持有的资源,不能释放
资源分配图
中间的正方形代表实例数,也可以画成圆点之类的
四个必要条件
- 互斥条件(Mutual Exclusion): 至少有一个资源必须是非共享的,即每次只有一个进程(或线程)能访问该资源。如果一个进程正在使用某个资源,其他进程必须等待该资源释放。
- 占有并等待条件(Hold and Wait): 一个进程必须持有至少一个资源,并且在等待获得其他进程持有的资源。在这种情况下,进程不会释放已经拥有的资源,直到获得所有需要的资源。
- 不剥夺条件(No Preemption): 已分配给进程的资源不能被强制剥夺。即,进程必须自己释放资源,系统不能强行从进程中回收资源。
- 循环等待条件(Circular Wait): 存在一种进程资源的循环等待关系,即进程 A 等待进程 B 持有的资源,进程 B 等待进程 C 持有的资源,而进程 C 又等待进程 A 持有的资源,从而形成一个循环。
解决
死锁预防:
- 破坏死锁的必要条件之一:可以通过改变进程请求资源的方式来破坏死锁的某一条件。例如,可以使用 锁顺序(如规定所有进程必须按照一定顺序请求资源),或者强制 不允许占有并等待(即进程在请求资源时必须一次性请求所有资源,否则就释放已持有的资源并重新请求)。
死锁避免:
- 银行家算法:这是一个常见的死锁避免算法,用来判断当前的资源请求是否会导致死锁。如果请求资源后系统处于安全状态,允许分配,否则拒绝分配,直到系统处于安全状态。
死锁检测与恢复:
- 通过系统监控与定期检查,检测是否有死锁发生。如果发生死锁,系统可以采取某种恢复措施(例如终止某些进程或强行回收资源)。
资源回收策略:
- 一些系统使用 资源剥夺 或者 强制回收资源 的策略,即强制终止某些进程或从进程中回收资源,这可以避免死锁,但这种方法会影响进程的正常执行。
管程
管程(Monitor),把分散在各进程中的临界区集中起来进行管理;避免了直接使用低级同步原语(如信号量和互斥锁)的复杂性。
一个管程定义了一个数据结构和在该数据结构上能为并发进程所执行的一组操作
进程通信
IPC(Inter-Process Communication)
进程通信机制
- 管道(Pipe):在两个进程之间传递数据。
- 消息队列:进程通过消息传递的方式进行通信。
- 共享内存:多个进程通过共享内存区域进行高效的数据交换。
- 套接字(Socket) : 套接字是一种网络通信机制,允许不同机器上的进程之间进行通信。
- 远过程调用(RPC) : Remote Procedure Call,允许一个程序调用另一个位于不同计算机上的程序,就像调用本地程序一样。在分布式应用中很常见
进程通信策略
- 共享内存通信:如果进程需要交换大量数据,操作系统选择通过共享内存来提高效率。
- 消息传递通信:对于较小的数据量或进程间的异步通信,操作系统选择消息队列或管道进行通信。
CPU
衡量指标
- CPU利用率:反映CPU的使用情况,目标是提高利用率。
- 吞吐量:单位时间内完成的进程数。
- 周转时间:进程从提交到完成的总时间。
- 等待时间:进程在就绪队列中等待的时间。
- 响应时间:进程提交到首次响应的时间。
- 带权周转时间:周转时间与进程执行时间之比。
- 公平性:衡量进程资源分配的公平程度。
- 响应比:进程的响应性,考虑等待和执行时间。
机制
- 时钟中断:硬件定时器产生定时中断,触发操作系统进行进程调度。
- 上下文切换:保存当前进程状态并加载下一个进程状态,实现多任务并发执行。
- 调度队列:管理就绪进程,决定哪个进程获得CPU。
中断
硬件中断(Hardware Interrupts)
- 外部设备中断:当外部设备(如键盘、鼠标、打印机等)需要CPU的服务时,它们会发送一个中断请求给CPU。例如,当你按下键盘上的一个键时,键盘控制器就会向CPU发送一个中断请求,告诉它有新的按键信息需要处理。
- 时钟中断:由系统的定时器产生,用于实现时间片轮转、调度等操作。
- I/O中断:与输入输出设备有关,用于通知CPU数据传输完成或其他I/O操作的状态变化。
- 硬件故障中断:比如电源故障、内存校验错误等,这些中断通常用于报告硬件问题。
软件中断(Software Interrupts)
- 系统调用:用户程序可以通过软件中断来请求操作系统提供服务。例如,文件读写、网络通信等操作都是通过系统调用来实现的。
- 异常(Exceptions):当程序遇到错误情况,如除以零、非法指令、访问越界等,会产生异常中断,让操作系统或运行时环境进行相应的错误处理。
- 断点(Breakpoints):调试程序时使用的中断,可以在指定代码行设置断点,使程序运行到该处时暂停,以便开发者检查程序状态。
策略
调度策略
- FCFS(先来先服务, First Come, First Served):
- 按照进程到达的顺序进行调度,即最先到达的进程最先得到CPU执行。
- 优点是简单易实现;缺点是可能导致长队列和低效的CPU使用,尤其是当有一个长时间运行的进程时。
- SJF(短作业优先/短进程优先, Shortest Job First):
- 选择预计执行时间最短的下一个进程进行调度。
- 包括非抢占式(一旦开始运行就不会被中断)和抢占式(Shortest Remaining Time First, SRTF)两种形式。
- 优点是可以减少平均等待时间;缺点是对长进程不利,可能会造成饥饿现象。
- HRRN(最高响应比优先, Highest Response Ratio Next):
- 响应比 = (等待时间 + 服务时间) / 服务时间,即
R=(W+S)/S= W/S+1
,每次选择响应比最高的进程,即当一个进程执行完后,调度等待了相对最久的一个进程。 - 该算法综合考虑了等待时间和执行时间,试图平衡短作业和长作业。
- 优点是可以提供较好的公平性和效率;缺点是计算相对复杂。
- 响应比 = (等待时间 + 服务时间) / 服务时间,即
- Round Robin(轮转, Round Robin):
- 使用固定的时间片(time slice)轮流给每个就绪进程分配CPU时间。
- 当一个进程用完其时间片后,它被移至队列末尾,等待下一轮调度。
- 优点是能够快速响应交互式用户的需求;缺点是如果时间片设置不当,可能会导致过多的上下文切换或低效的CPU使用。
- Multilevel Feedback Queues(多级反馈队列, MLFQ):
- 设有多个优先级队列,新进程通常从最高优先级队列开始。
- 如果进程在高优先级队列中未完成其时间片,则被降级到下一个较低优先级队列。
- 进程可以在一段时间内没有获得CPU时间后重新提升优先级。
- 优点是能够在同一个系统中同时支持交互式和批处理任务;缺点是配置和管理较为复杂。
抢占策略
- 抢占式调度:操作系统可以中断进程,切换到另一个进程。
- 非抢占式调度:进程完成或主动释放CPU之前不会被打断。
三级调度
- 长程调度(作业调度):决定哪些程序加载到内存中成为进程。
- 中程调度:管理进程在内存和磁盘交换区之间的换入换出。
- 短程调度(进程调度):选择就绪进程分配CPU执行。
其他调度
实时调度
在实时系统中,某些任务是实时任务,它必须能够满足时限要求,即,满足给定的一个最后期限,最后期限指定任务开始时间或结束时间,如智能网联汽车、机床,一般都是工业操作系统。
分为硬实时和软实时
多处理器调度
对称调度 : 让一个处理器(主处理器)处理所有调度决定、I/O处理以及其他系统活动,其他处理器只执行用户代码。
非对称调度 : 即每个处理器自我调度
处理器亲和性 : 当一个进程运行在一个特定的处理器上时,会缓存该进程的一些数据和上下文,如果进程需要迁移处理器,就会产生很高的代价,所以会将进程绑定在一个CPU上
负载均衡 :
- 推迁移:一个特定的任务周期性地检查每个处理器的负载,如果发现不平衡, 那么通过将进程从超载处理器推到空闲或不太忙的处理器,从而平均分配负载。
- 拉迁移:当空闲处理器从一个忙的处理器上拉一个等待任务时,发生拉迁移。
负载均衡往往会抵消处理器亲和性的好处。
饥饿
Starvation,一个可执行的进程,被调度器持续忽略,以至于虽然处于可执行状态却不被执行
原因:
- 优先级反转: 高优先级的进程可能会被低优先级的进程一直阻塞,特别是在优先级调度策略中,如果低优先级的进程长时间占用资源,高优先级的进程就会被迫等待,从而导致饥饿。
- 不公平的调度策略: 如果调度算法不公平,某些进程可能会被反复推迟。例如,某些算法可能会优先考虑具有较高优先级或者频繁轮转的进程,而忽略低优先级或长时间没有运行的进程,导致它们无法得到足够的执行机会。
- 资源竞争: 当系统中的资源有限,而多个进程同时竞争同一资源时,某些进程可能长期得不到资源的分配。例如,多个进程请求相同的锁、内存或I/O设备,但没有合适的机制来保证它们公平竞争资源。
- 死锁: 在死锁的情况下,进程可能永远被阻塞,因为它们互相等待对方释放资源。这也会导致某些进程无法执行,类似于饥饿。
- 长时间的I/O等待: 如果某些进程长时间等待I/O操作(如磁盘读取或网络传输),而调度系统优先调度计算密集型进程,I/O密集型的进程就可能发生饥饿。
解决方法:
- 优先级调整:采用动态优先级调整机制,防止低优先级进程永远无法得到执行。
- 轮转调度:通过轮转调度算法来公平地分配CPU时间,避免某些进程一直被忽略。
- 资源公平分配:通过公平的资源分配策略(如公平共享资源、限制锁的持有时间等)来减少资源竞争导致的饥饿问题。
内存
机制
- 分页:将内存分割成固定大小的页面,避免内存碎片。
- 虚拟内存:通过页面置换算法,将部分内存内容临时存储到磁盘,扩展可用内存。
- 分段 : 对虚拟地址进行分段管理,如堆,栈,dk’ma
- 内存保护:通过页表或段表,防止进程访问未分配的内存区域。
策略
- 内存分配:
- 首次适配:从空闲内存块中选择第一个合适的分配。
- 最佳适配:选择最适合的内存块进行分配,减少碎片。
- 伙伴系统:通过将内存块分成大小相等的“伙伴”来管理内存。
- 页面置换策略:
- FIFO:替换最早加载的页面,存在Belady现象(物理页越多,缺页率却越高的情况,因为最开始加载的页面很可能很有用),很少单独使用。
- LRU:替换最长时间未被访问的页面。
- 最佳算法(Optimal):替换最不可能被使用的页面。
- **时钟页面置换算法(Clock) **: 平衡了复杂度和性能的页面替换策略
- 内存保护策略:
- 访问控制:限制进程只能访问自己分配的内存区域。
- 共享内存:多个进程共享一块内存,用于进程间通信。
分页
物理内存划分为帧(frame), 逻辑地址划分为页(page)
建立逻辑地址转化物理内存的方案
- 页表,帧与页的映射
- cpu的MMU(Memory Management Unit)/TLB(快表)
帧 : 将物理地址分为两部分,帧号 f (F位)和帧内偏移 o (S位)
页 : 将逻辑地址分为两部分,页号 p (p位)和页内偏移 o (S位)
虚拟内存
虚拟存储策略
两种情况
- 手动覆盖(overlay) : 程序过大,只把需要的指令和数据存在内存之中,需要程序员将程序分为若干的功能模块,增加了程序员的优化负担
- 自动交换(swapping) : 程序过多,把暂时不能执行的挂起在外存中,需要将地址换来换出,增加了处理器开销
虚存技术
通用技术,基于程序执行的时间局部性和空间局部性,装载的时候只装当前需要执行的部分页面
虚存页表项
- 访问位 : 是否被访问过(用于页面置换算法)
- 修改位 : 是否被修改过(回收时是否写入外存)
- 保护位 : 允许的访问权限,如读写等
- 驻留位 : 1为在内存中,0为在外存中,访问会触发缺页中断
性能评估
使用有效存储器访问时间EAT(effectivememory access time),
EAT=访存时间×页表命中率+PF处理时间×PF概率
进程页面置换算法
LIFO和LRU的规则跟名字一样,clock时LRU的近似,FIFO的改进
clock是LRU的近似,FIFO的改进,基本思路如下
- 使用访问位,初始化为0,当被访问后设为1
- 使用一个指针,指向最老的页面,当缺页时,如果指针位置的访问位为0,则淘汰该页,如果为1,则指针下移
全局分配算法
可以动态分配一个进程有多少页框
- 常驻集 : 进程运行时,实际驻留在内存里的页面集
- 工作集 : 进程在过去一段时间内访问过的页面集和
系统抖动 : 当分配的页面小于工作集时,频繁缺页导致运行很慢,随着进程数增加,每个进程分得的页面减少,这个情况就会很明显
解决方法
- 工作集策略 : 计算工作集近似得到需要的页帧数,如果页帧总数大于物理帧数,则需要减少进程
- 缺页率策略 : 检测缺页率,设置可接受的缺页率,根据实际缺页率和标准值进行动态调整进程的页帧
文件系统
文件系统负责文件的存储、读取、权限管理等。
机制
- 文件存储机制 : 索引分配、连续分配、链式分配等文件存储机制,用于决定如何在磁盘上分配空间。
- 文件权限管理机制 : 通过访问控制列表(ACL)、文件属性来管理文件的读、写、执行权限。
- 文件系统缓存机制 : 使用页缓存或缓冲区缓存来提高文件操作的效率,避免频繁的磁盘访问。
策略
- 文件分配策略
- 连续分配:将文件的所有块分配到磁盘的连续位置。
- 链式分配:每个文件块存储指向下一个文件块的指针。
- 索引分配:每个文件有一个索引块,索引块存储文件块的位置。
- 文件权限控制策略
- 最小权限原则:通过ACL等机制,操作系统按照最小权限原则,为每个用户或进程分配最小的访问权限。
- 文件缓存策略
- 写回缓存(Write-back Cache):将数据缓存在内存中,延迟写入磁盘,提高性能。
- 写直达缓存(Write-through Cache):数据同时写入缓存和磁盘,确保数据一致性。
文件
文件是操作系统用来存储数据的基本单位,文件的内容可以是文本、二进制数据、图像、音频或任何其他类型的数据。文件有一个逻辑结构,包含数据区、控制信息等。
逻辑结构
- 堆结构文件,可以快速追加不同类型的记录,相当于redis
- 顺序结构文件,类似表格,可以快速进行增删改查操作,相当于mysql
- 散列结构文件,计算文件的hash值得到记录编号,相当于图床,oss之类的存储多媒体
物理结构
- 连续文件 : 将一个文件中逻辑上连续的信息存放到存储介质的依次相邻的物理块上便形成顺序结构,跟顺序表的优缺点类似,顺序读写的效率高,但是修改很麻烦
- 链接文件 : 分成若干不连续的物理块中,类似链表
- 隐式链接文件 : 每个文件块记录或许指针,可靠性低,依赖强
- 显式链接文件 : 将指针放在一张文件访问表(FAT)里面,便于并行读取
- 索引文件 : 文件也存在不连续块中,为每个文件建立索引表,通过文件目录,查询到索引表,从而查询得到实际的物理块号,类似hash表或B+树
读写方式
- 顺序读写 : 按照文件的逻辑地址顺序存取
- 对于无结构的流式文件,每读取文件中的一个字符,文件内部指针便向后移动指向下一个字符。文件指针不能回溯。
- 对于记录型的文件,固定长度的记录实现起来是比较简单的。在读写记录时,总是读完上一条记录,才能接着读写逻辑号紧邻的下一条记录。
- 直接读写(随机读写法)
- 索引读写 : 为文件创建索引hash表
文件系统
文件系统负责管理文件的存储和访问,提供文件命名、存取、保护、组织和管理等功能。它将文件的逻辑结构映射到物理存储设备(如硬盘)的存储空间。
文件控制块
FCB(File Control Block),是操作系统为管理文件而设置的一组具有固定格式的数据结构,存放了为管理文件所需的所有属性信息,如下
目录管理
文件目录 : 文件名和文件物理位置之间的映射关系
基本功能 :
- 实现“按名存取”
- 快速检索文件目录
- 实现文件共享
- 允许文件重名
分类 : 一级,二级,多级目录. 现代操作系统都用多级目录
空闲空间管理
- 位视图 : 对每个磁盘块采用一个位来标注是否使用,形成一张位图(bitmap), 当标注为0时表示空闲.
- 空闲块列表 : 用空闲块号+空闲块数来记录空闲的空间.即指针+偏移
- 空闲链表法 : 将空闲块串成一条链
文件存取控制
文件共享
- 系统打开文件表(Open file table) : 整个操作系统只维护一张表,记录已打开的文件的信息,如FCB号,共享计数等
- 用户打开文件表 : 每个用户进程都有一张的表,用于记录用户打开的一些文件信息,如文件描述符fd和指向系统打开软件表项的指针,通过指针的方式,实现了进程间文件共享
文件保护
- 口令保护 : 用户建立时提供一个口令,并告诉想要共享的用户该口令
- 加密保护 : 在写入硬盘时进行加密
- 权限控制 : 通过存储控制矩阵和存储控制表.都是指定用户对单个文件的权限,如
rwx
,前者更加全面,建立用户-文件的完整表,后者更加轻量,对每个文件分别建立访问权限表,可以只设定特殊用户
VFS
虚拟文件系统 VFS(VirtualFileSystem),隐藏硬件具体细节,位所有设备提供统一的接口,可支持多种文件系统,常见应用如下
- 多文件系统支持:VFS 使得操作系统能够支持多种不同的文件系统,例如 ext4, NTFS, FAT32, XFS, Btrfs 等,而无需为每种文件系统编写专门的应用程序。
- 网络文件系统 (NFS):通过VFS的支持,远程服务器上的文件可以像本地文件一样被访问,这大大简化了分布式计算环境中的资源共享。
- FUSE (User-space file systems):FUSE 允许用户在用户空间中实现自己的文件系统,而不必修改内核代码。这对于快速开发和测试新文件系统非常有用。
- 容器技术:在 Docker 和 Kubernetes 等容器化平台中,VFS 被用来管理容器之间的文件系统隔离,确保每个容器都有独立的文件系统视图。
- 云存储服务:许多云存储服务(如 Amazon S3, Google Cloud Storage)也利用了类似VFS的概念,提供给用户一个类似于传统文件系统的接口,但实际上数据可能存储在全球分布的数据中心中。
IO设备
设备管理负责管理计算机硬件和外设,如打印机、硬盘、显示器等。
机制
设备驱动程序:提供设备与操作系统之间的接口,使得操作系统能够与硬件设备进行交互。
中断机制:硬件设备通过中断机制向CPU报告事件,操作系统通过中断处理程序响应设备请求。
设备分配数据结构 :
- 设备控制表DCT,每个设备配置一张用于记录设备使用情况的表
- 控制器控制表COCT,每个控制器设备配置一张用于记录本控制器情况的表
- 系统设备表 SDT,记录系统中全部设备的情况,每个设备占一个表目,包括设备类型、设备标识符、设备控制表、设备驱动程序入口等
策略
设备分配策略 : 抢占式与非抢占式策略:决定设备在多个进程或任务之间的分配方式。
I/O调度策略,主要是磁盘
- 先来先服务(FCFS):根据请求到达的顺序调度I/O请求。
- 最短寻道时间优先(SSTF):选择距离当前磁头位置最近的I/O请求。
- SCAN :有时称为电梯算法,磁盘头从一个方向开始扫描,直到到达最远端,再反向扫描。其变种C-SCAN扫描完一遍之后直接返回开头
- LOOK调度 : 只需要移动到需要访问的地址的最远,而不是到达最远端,对应的有C-LOOK
控制器
一般主板上的南桥芯片,基本功能如下
- 数据缓冲 : IO设备速率低,缓冲一部分io信息后再交给高速的CPU处理
- 差错控制 : 发现错误,将差错检测码置位并向CPU报告,从而作废重传
- 数据交换 : 通过总线与CPU进行数据交换
- 标识设备状态 : 是否完成操作
- 接受CPU指令 : 完成简单的操作,如读取,写入,启动等
- 地址识别 : 解码设备地址来选择正确的设备
数据传输
-
轮询 :CPU不断测试IO状态端口,效率低
-
中断 : 设备完成操作后,向CPU发送中断信号
-
DMA(Direct Memory Access) : CPU将内存的处理外包给DMA
我去,有挂
-
通道 : 简单的处理器
驱动
操作系统通过驱动和硬件进行通信
win10安装包中,系统占1/3,而集成的通用驱动至少占1/2,所以各种硬件都能在脱机模式(离线)直接使用,win95只有44mb也是因为那个年代硬件少,驱动少.
如果驱动缺失,可以直接在设备管理器中联网更新驱动程序,而在联网状态会自动更新驱动,
而黑苹果难装也是因为能用的驱动少,很看硬件
驱动追求稳定,不最求最新
但通用驱动只支持最基本的功能,一些硬件的高级功能必须到官方下载专属的驱动,一般有主板,显卡需要自己安装驱动(主板集成了各种驱动)
显卡 : A卡(amd收购的ATI显卡)2d更强功耗小,更便宜,N卡(NVIDIA)3d更强(浮点数),优化好,效率高,游戏优化更好
引导方式
BIOS
BIOS(Basic Input/Output System,基本输入输出系统)设置为legacy时,会采用硬盘主引导记录MBR(Master Boot Record)进行引导
BIOS首先对CPU初始化;然后跳转到BIOS启动处进行POST自检;再采用读中断的方式加载各种硬件,完成硬件初始化后进入操作系统启动过程。
BIOS是16位汇编语言程序,只能运行16位实模式,可访问内存只有1MB。
传统BIOS启动由于MBR的限制,默认是无法引导超过2.1TB以上的硬盘。
UEFI
windows提供的,文件必须格式化为GPT格式,一种新型引导方式
UEFI则先运行预加载环境,直接初始化CPU和内存,CPU和内存若有问题,则直接黑屏;然后启动PXE,采用枚举方式搜索各种硬件并加载驱动,完成硬件初始化,再进入操作系统启动过程。
UEFI是32位或64位高级语言程序,突破实模式限制,可以达到要求的最大寻址。
UEFI支持硬盘容量更大,更常用。同时,它提供图形界面。
网络存储技术
DAS
直接网络存储(DAS)是指将存储设备通过SCSI接口或光纤通道直接连接到服务器上的方式。
这种连接方式主要应用于单机或两台主机的集群环境中,主要优点是存储容量扩展的实施简单、投入成本少、见效快。
NAS
网络附加存储(NAS)是一种将分布、独立的数据整合为大型、集中化管理的数据中心,以便于对不同主机和应用服务器进行访问的技术。
NAS中服务器与存储之间的通信使用TCP/IP协议,数据处理是“文件级” 。
SAN
SAN(Storage Area Network,存储区域网络),通常SAN由RAID阵列连接光纤通道(Fiber Channel)组成;
SAN和服务器以及客户机的数据通信通过SCSI命令而非TCP/IP,数据处理是“块级” 。
IP-SAN
网络存储的发展产生了一种新技术IP-SAN。
IP-SAN是以IP为基础的SAN存储方案,是IP存储技术应用的第三阶段,是完全端到端的、基于IP的全球SAN存储。
云存储
云存储是在云计算(Cloud computing)概念上延伸和发展出来的一个新的概念。
云计算是分布式处理、并行处理和网格计算的发展,是透过网络将庞大的计算处理程序自动分拆成无数个较小的子程序,再交由多部服务器所组成的庞大系统计算分析之后将处理结果回传给用户。