操作系统入门(一)
操作系统介绍
程序运行时会发生什么?
Von Neumann计算模型基本理念:
graph LR;
取指令 --> 解码 --> 执行
完成一条指令后,处理器将继续执行下一条指令,直到程序完成运行。
一种允许程序与设备交互,让程序共享内存,使程序运行变得容易的软件,这种软件被称为操作系统(Operating System, OS ),操作系统负责确保系统既易于使用又高效的运行。
虚拟化
关键问题:如何实现资源的虚拟化?
通过虚拟化技术(virtualization)将物理资源(cpu、内存、磁盘等)转换为虚拟形式,因此有时也将操作系统称为虚拟机。
为了方便用户使用,操作系统提供了一个标准库(standard library),其中包含几百个系统调用(也称之为接口(API)),以供程序调用来实现程序的运行、物理资源的访问等。
- 虚拟化让多个程序运行时共享物理资源,操作系统也被称为资源管理器,cpu,磁盘等都是系统的资源,操作系统主要扮演资源的管理者,做到高效或者公平。
实例1:CPU的虚拟化
查看如下代码:
1 |
|
该程序简单调用Spin()函数,反复检查时间并在运行一秒后返回,接着在屏幕上打印。
- 查看运行结果(之后所有代码运行环境皆为Ubuntu20.04)
1 |
|
运行时该程序会重复检查时间,直到一秒后,该程序会打印用户输入的参数,并且继续运行。
实例2:内存的虚拟化
现代及其提供的物理内存模型非常简单,内存就是一个字节数组,通过地址访问相应的数据,进行更新或者写入操作时还需要给定相应地址的数据。程序运行时所有结构都保存在内存中,并且通过各种指令来访问,每次读取指令都会访问内存。
查看如下代码:
1 |
|
该程序使用malloc()分配一些内存,运行结果如下:
1 |
|
该程序首先分配一些内存,之后打印出内存对应的地址,将数字0放入分配的内存中第一个空位,最后延迟一秒并递增p中保存的地址值,每个语句还会打印正在运行程序的标识符(PID),对于每个进程PID为唯一。
并发
关键问题:如何构建正确的并发程序
如何构建正确的程序?操作系统需要提供什么?硬件需要有什么机制?如何利用他们解决并发问题?
- 一个多线程程序
1 |
|
主程序利用Pthread_create()创建两个线程,每个线程都在work()函数中运行,由用户的输入决定work()函数中循环的运行次数,最后输出玄幻次数counter,查看不同参属下运行的次数:
- loop = 1000
1 |
|
- loop = 5000
1 |
|
- loop = 10000
1 |
|
- loop = 100000
1 |
|
可以看到当循环次数较小时候,当loop = n时,输出为2n,这非常好理解,因为共有两个线程,当loop值更大时,我们使输入为100000,最终结果不为200000,并且再次运行,结果又产生了不同。
1 |
|
造成这种现象的原因是该语句的执行过程需要三条指令集控制:
graph LR;
将数值加载到寄存器 --> 将数值递增 --> 将数值放回内存
这一过程不具有原子性(automically)。
持久性
关键问题:如何持久的存储数据
持久性的实现需要哪些技术?那些策略和机制能高性能的实现持久性?面对软硬件故障如何实现可靠性?
操作系统中的磁盘管理软件称为文件系统,负责将用户创建的任何文件存储在磁盘上。
操作系统不会为磁盘创建虚拟资源,用户之间需要共享文件系统中的信息,查看如下代码:
1 |
|
该程序发出三个调用来实现了一个文件的写入,文件系统的实际写入过程如下:
graph LR;
确定数据的驻留位置 --> 发出IO请求 --> 读取现有结构 --> 在文件系统中对位置进行记录
出于性能原因,IO操作会延迟进行。为了预防IO操作中发生系统异常,多数文件系统拥有日志(journaling)或写时复制(copy-on-write)这些复杂的写入协议。为了使不同的同游操作更有效,文件系统采用了不同的数据结构和访问方法,从简单的列表到B-TREE。
操作系统设计目标
操作系统主要功能
- 取得物理资源并进行虚拟化
- 处理并发
- 持久化存储文件
最基本目标:建立抽象
抽象使编写大型程序称为可能,下面是一个简单的抽象过程:
graph LR;
晶体管 --> 逻辑门 --> 汇编语言 --> 高级程序语言
- 提供高性能
- 在程序与OS之间提供保护
- 可以不间断运行
- 安全性
- 移动性
- …………
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!