《现代操作系统》读书笔记
操作系统的作用
操作系统的作用是在用户层和硬件层之间搭建起沟通的桥梁:
操作系统对用户和工作在操作系统上的程序员隐蔽了硬件的细节,使得用户有更好的体验。
举个栗子:比如你要想在屏幕上绘制线段,如果你要自己写操作系统的话,你得和显卡打交道,具体要做的是使用BIOS中断服务打开VGA显示模式,然后向显存(VRAM)的0xA0000地址处写入像素的数据。但是如果你是在操作系统的基础上绘制线段的话,你只需要调用一下操作系统的API即可(或者图形库,图形库本质也是调用API),完全不需要考虑显存的问题。
内核
内核(Kernel)是指操作系统的最基本的部分,一般可以提供的功能有:
- 管理进程
- 管理文件系统
- 管理内存
- 管理网络系统
- 设备驱动程序
内核将直接和硬件打交道(比如上面所说的VRAM),并且保护硬件不受用户程序乱用。显然,如果用户程序可以像显存写入数据,那你将会在屏幕上任意的地方没有限制地绘制线段,可能会将整个界面弄得一团糟。如果将磁盘的控制权释放给用户将会更加糟糕,用户可以随意更改磁盘上的文件,甚至是内核源代码。所以对硬件的保护是有必要的。
内核还有可能提供系统调用或者API给用户。
中断
中断也是内核管理的一部分,中断分为两种:硬件中断和软件中断。硬件中断又分为两种:可屏蔽中断和不可屏蔽中断:
- 硬件中断:由硬件带来的中断,像是磁盘的读准备中断等。
- 可屏蔽中断:可以被屏蔽的中断。被屏蔽之后内核不会对中断做出响应。
- 不可屏蔽中断:不可以被屏蔽的中断,一定会发生
- 软件中断:通过软件代码来指定产生中断
中断就是中断当前的事情,执行指定的事情的意思。也就是说,如果发生中断,内核会暂停当前程序的允许,转而去执行中断所指定的程序。执行完之后再返回执行程序(不一定执行中断发生前的程序,因为有些中断就是为了切换用户程序才发生的)。
API
API是Application Programmer Interface,通俗的说就是应用程序接口,是一系列运行在用户空间的,可供程序员使用的函数和变量。系统API就是操作系统提供的一些函数和变量,库API就是库提供的函数和变量。
系统调用
系统调用是一系列运行在内核的函数,然是却可以被用户程序调用。在Linux中,系统调用是用户访问内核的唯一途径。
当用户程序进行系统调用时,操作系统会从用户控件转移到内核空间,然后在内核控件中执行系统调用。
比如说,现在用户想要从磁盘上读取一份文件,但是由于内核将磁盘的读写权限保护起来了,用户程序不能直接使用。这个时候用户程序只能进行一个系统调用,切换到内核空间,这个时候由于内核有权限读取磁盘,所以内核会运行磁盘服务,读取数据后将数据返回给用户,并再次进入用户空间。
并发和并行
并发是指在单个CPU下,由于进程调度算法,给用于一种多个进程同时运行的错觉(其实一个CPU同一时间只能运行一个进程,通过调度算法来回切换时间片给出同时运行错觉)。而并行则是真正意义上的同时进行,并行是指多个CPU的进程同时执行。
栈和堆
栈是一种特殊的数据结构,符合先进后出。而堆一般指一块随机存储的内存。在NASM汇编中,栈就是section .stack
中的数据,而堆则是section .bss
中的数据。在C语言中,手动声明的变量时存放在栈中的,这样在程序结束后操作系统会回收栈内的数据;而是用malloc等内存分配函数所分配的数据就是在堆中。在分配的时候操作系统在内存中查找一块符合大小的空白的区域,并将区域的第一个字节的地址返回。系统不会跟踪这块区域,所以在程序结束前必须手动free以防止内存泄漏。
现代操作系统大部分都会增加对应的结构来记录程序在堆上分配的内存,以便在程序内存关闭后同样清空堆。但是并不是所有的操作系统都存在这种机制(称为内存自动回收)。