os

「操作系统导论」学习笔记

Posted by 小石匠 on 2019-12-10

书籍豆瓣链接:《操作系统导论》

开始学习日期: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区域
数据区域