书籍豆瓣链接:《操作系统导论》
开始学习日期:10-27
预计完成时间:1-24
实际完成时间:
虚拟化
虚拟化CPU
在硬件的支持下,CPU交替执行多个程序,造成一种系统拥有非常多的虚拟CPU的假象。将单个CPU转换为看似无限数量的CPU,从而让多个程序看似同时运行,这就是虚拟化CPU。
进程
进程创建
1 2 3 4
| 1. 程序最初是以可执行文件的形式存储在磁盘上的,运行程序第一件事就是从磁盘加载可执行文件到内存中(bss,data,text)。 2. 然后给程序的堆和栈空间分配内存。 3. 接着执行一些其他初始化任务(比如打开3个文件描述符:标准输入、标准输出、错误) 4. 启动程序,调转到main函数,OS将CPU控制权交给新创建的进程,从而程序开始执行。
|
进程状态
1 2 3
| 运行:占有CPU,正在执行指令; 就绪:准备执行,由于某些原因,在等待CPU资源,具备直接执行的条件; 阻塞:正在等待某些条件,不具备直接执行的条件;
|
进程控制块
1 2
| 储存关于进程信息的个体结构称为进程控制块(Process Control Block,PCB)。在linux内核中定义为task_struct。包含进程状态、打开的文件、进程的地址空间、挂起的信号、寄存器上下文等内容;
|
进程API
1 2 3
| fork 创建子进程,使用写时拷贝,读共享写隔离 wait 等待子进程完成 exec 从可执行程序中加载代码和静态数据,执行新程序
|
受限直接执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 用户模式下,应用程序不能完全访问硬件资源 内核模式下,操作系统可以访问机器的全部资源,还提供了陷入内核和从内核返回
LDE两个阶段: 1. 系统引导时,内核初始化陷阱表 2. 运行进程时,在使用从陷阱返回,开始执行进程之前,内核设置了一些内容。进程发出系统调用,会重新陷入操作系统
中断分类 1. 外部中断,io,时钟,控制台中断,由硬件引起,异步 2. 内部中断,又称异常,由cpu内部事件或程序执行中的事件引起的过程,由软件引起。同步 3. 陷阱,陷阱是主动、有意的,且其发生时间是确定的。而中断是被动,无意的,它的发生时间是不可预测的 时钟中断,操作系统中预先配置的终端处理程序会运行
上下文切换:进程在进行切换时,OS会保存进程A的寄存器的值,然后恢复待执行进程B的寄存器,OS将控制权移交给待执行进程B,进程B开始运行
|
虚拟化内存
每个进程有自己的虚拟地址空间,操作系统将映射地址空间到物理内存,进程间地址空间相互隔离。对于正在运行的程序,好像完全拥有自己的物理内存。
内存操作api
1 2
| 栈内存,自动内存,申请和释放编译器隐式管理 堆内存,malloc和free程序员手动完成
|
常见错误
1 2 3 4 5 6
| 忘记分配内存 段错误 没有分配足够的内存 缓冲区溢出 忘记初始化分配的内存 未知的值 忘记释放内存 内存泄漏 用完之前释放内存 悬挂指针 重复释放内存 结果未定义
|
地址空间管理
1 2 3 4
| 内存管理单元(MMU),基址寄存器,界限寄存器,整个进程空间是连续内存 操作系统有两种方法,来解决大多数空间管理问题: 1. 将空间分割成不同长度的分片,就想虚拟内存管理中的分段,堆,空闲列表管理空闲空间。会造成空间本身碎片化,难以再利用。 2. 将空间分割成相同长度的分片,比如分页,一页4kb
|
地址转换
1 2 3 4 5 6 7 8 9 10 11
| 1. 每次都要读内存访问页表 TLB,地址转换缓存 缓存 时间局部性 空间局部性
2. 页表太大,消耗内存太多 多级页表,分页分段 tlb是页表的缓存,而内存时物理页的缓存
tlb未命中,由硬件或者操作系统在页表中查找页,如不存在引发缺页中断,将请求发送到磁盘,将页读取到内存中
如果内存被超额请求时,不停地换页,称为抖动
|
内核进程空间
1 2 3
| 地址空间上半部 内核空间 下半部 系统空间 用户进程共享内核地址空间,内核地址空间的页常住内存 内核地址空间存放系统代码和数据,包括页表
|
并发
线程提供了在同一程序内共享内存地址空间运行的机制。线程机制支持并发程序设计技术。
linux实现线程的机制非常独特,从内核的角度看,他并没有线程的概念。linux把所有线程都当进程来实现。进程和线程都用task_stuct结构进行管理,线程仅仅被视为一个与其他进程共享某些资源(比如地址空间)的进程。windows和Sun Solaris等操作系统的实现差异非常大。这些系统都在内核中提供了专门支持线程的机制。
线程有自己的程序计数器(PC),寄存器,线程栈
线程控制块(TCB),保存每个线程的状态,控制线程之间的上下文切换
1 2 3 4
| 临界区: 访问共享资源的一段代码,资源通常是一个变量或数据结构 竞态条件: 出现在多个执行线程同时进去临界区,试图更新共享的数据结构 不确定性: 程序由一个或多个竞争条件组成,导致程序输出结果不确定 互斥元语: 保证只有一个程序进入临界区
|
锁
1 2 3 4 5 6 7 8
| 希望原子式执行系列指令,但由于单处理器上的中断(或者多处理器并发执行),使用锁可以实现 互斥锁,资源被占用,资源申请者只能进入睡眠状态 但自旋锁会一直自选,知道锁可用。需要抢占式调度器,否则,自旋锁在单cpu上不会放弃cpu。自旋时间比进程调度短,自旋锁就更加适合。
基于锁的数据结构 并发计数器 并发链表 并发队列
|
条件变量
1 2 3 4 5
| 线程需要检查某个条件,满足之后,才会继续运行 可以使用一个条件变量,来等待一个条件变真 wait 释放锁,调用线程失眠,被唤醒时必须重新获取锁 signal 唤醒等待在某个条件变量上的睡眠线程 broadcast 覆盖条件,唤醒所有等待在条件变量上的睡眠线程
|
信号量
1 2 3
| 信号量可以用作锁和条件变量 sem wait 减一,如果<0等待睡眠 sem post 加一,唤醒一个睡眠线程
|
常见并发问题
1 2 3 4 5 6 7 8 9 10 11 12
| 非死锁缺陷 1. 违反原子性 2. 错误顺序 死锁缺陷 1. 产生死锁的条件 互斥:对于需要的资源进行互斥访问 持有并等待:线程持有资源,同时等待其他资源 非抢占:线程获得的资源,不能被抢占 循环等待: 2. 解决方法 trylock 活锁 cas
|
持久性
总线
1 2 3 4
| 内存总线,连接内存系统 通用io总线,连接图像或其他高性能io 外围总线,将最慢的设备链接到系统,磁盘鼠标等 从上往下,速度越来越慢,造价便宜
|
直接内存访问DMA
1
| DMA 直接内存访问.就是数据不经过CPU.直接由内存和硬盘或者内存和硬件进行数据通信的方式.这种过程总.又CPU发出命令告诉哪些数据从内存中读写到那里.然后内存通过总线执行,数据传输完成够通知CPU.CPU只参与传输的开头和结尾.
|
raid 廉价冗余磁盘阵列
1 2 3 4 5 6 7 8 9
| raid0条带化 小块 文件跨多个磁盘条带化,增加读写并行性。增加定位时间 大块 减少并行性,减少定位时间 raid1镜像 对于每个逻辑块保留两个副本 raid4奇偶校验 加个逻辑校验盘,允许一个磁盘故障,奇偶校验盘是性能瓶颈 raid5旋转奇偶校验 每个条带的奇偶校验块在不同的磁盘上
|
文件和目录
1 2 3 4 5
| 目录项,所包含的文件的文件名,以及该文件的inode号 硬链接 ln 对同一个inode创建新的引用 符号链接 ln -s 将链接指向文件的路径名作为链接文件的数据
|
文件系统接口
1 2 3 4 5 6
| strace 跟踪程序在运行时所做的每个系统调用 stat 获取文件信息,文件元数据 open write 文件系统会将写入在内存中缓冲 fsync 强制将所有脏数据写入磁盘
|
文件系统实现
1 2 3 4 5
| 超级块 包含整个文件系统信息,卷的大小,有多少inode,指向空闲链表头部指针 inode位图 数据位图 inode区域 数据区域
|