操作系统概述
1.什么是操作系统
操作系统的主要组成包括:
- 操作系统内核:操作系统的核心部分,负责控制计算机的硬件资源并为用户和应用程序提供服务。
- 系统工具和软件库:为操作系统提供基本功能的软件,包括工具软件和系统软件库等。
- 用户接口:是操作系统的外壳,是用户与操作系统交互的方式。用户接口包括图形用户界面(GUI)和命令行界面(CLI)等。
操作系统内核主要组成部分包括:
- 进程/线程管理:内核负责管理系统中的进程或线程,创建、销毁、调度和切换进程或线程。
- 内存管理:内核负责管理系统的内存,分配和回收内存空间,并保证进程之间的内存隔离。
- 文件系统:内核提供文件系统接口,负责管理存储设备上的文件和目录,并允许应用访问文件系统。
- 网络通信:内核提供网络通信接口,负责管理网络连接并允许应用进行网络通信。
- 设备驱动:内核提供设备驱动接口,负责管理硬件设备并允许应用和内核其他部分访问设备。
- 同步互斥:内核负责协调多个进程或线程之间对共享资源的访问。同步功能主要用于解决进程或线程之间的协作问题,互斥功能主要用于解决进程或线程之间的竞争问题。
- 系统调用接口:内核提供给应用程序访问系统服务的入口,应用程序通过系统调用接口调用操作系统提供的服务,如文件系统、网络通信、进程管理等。
一个典型的UNIX操作系统的组成示意图:
2.操作系统调用接口
1.API与ABI
API:单一编程语言的函数库的编程接口。
ABI:接口描述规范。
系统调用接口通常面向应用程序提供了 API 的描述,但在具体实现上,还需要提供 ABI 的接口描述规范。
应用程序就不能直接以函数调用的方式访问操作系统的函数,以及直接读写操作系统的数据变量。不同类型的应用程序可以通过符合操作系统规定的系统调用接口,发出系统调用请求,来获得操作系统的服务。操作系统提供完服务后,返回应用程序继续执行。
2.系统调用接口与功能
对于通用的应用程序,一般需要关注如下问题:
- 一个运行的程序如何能输出字符信息?如何能获得输入字符信息?
- 一个运行的程序可以要求更多(或更少)的内存空间吗?
- 一个运行的程序如何持久地存储用户数据?
- 一个运行的程序如何与连接到计算机的设备通信并通过它们与物理世界通信?
- 多个运行的程序如何同步互斥地对共享资源进行访问?
- 一个运行的程序可以创建另一个程序的实例吗?需要等待另外一个程序执行完成吗?一个运行的程序能暂停或恢复另一个正在运行的程序吗?
操作系统主要通过基于 ABI 的系统调用接口来给应用程序提供上述服务,以支持应用程序的各种需求。
操作系统的大致功能:
- 进程(即程序运行过程)管理:复制创建进程 fork 、退出进程 exit 、执行进程 exec 等。
- 线程管理:线程(即程序的一个执行流)的创建、执行、调度切换等。
- 线程同步互斥的并发控制:互斥锁 mutex 、信号量 semaphore 、管程 monitor 、条件变量 condition variable 等。
- 进程间通信:管道 pipe 、信号 signal 、事件 event 等。
- 虚存管理:内存空间映射 mmap 、改变数据段地址空间大小 sbrk 、共享内存 shm 等。
- 文件 I/O 操作:对存储设备中的文件进行读 read 、写 write 、打开 open 、关闭 close 等操作。
- 外设 I/O 操作:外设包括键盘、显示器、串口、磁盘、时钟 … ,主要采用文件 I/O 操作接口。
编号 | 系统调用 | 所在章节 | 功能描述 |
---|---|---|---|
1 | sys_exit | 2 | 结束执行 |
2 | sys_write | 2/6 | (2)输出字符串/(6)写文件 |
3 | sys_yield | 3 | 暂时放弃执行 |
4 | sys_get_time | 3 | 获取当前时间 |
5 | sys_getpid | 5 | 获取进程id |
6 | sys_fork | 5 | 创建子进程 |
7 | sys_exec | 5 | 执行新程序 |
8 | sys_waitpid | 5 | 等待子进程结束 |
9 | sys_read | 5/6 | (5)读取字符串/(6)读文件 |
10 | sys_open | 6 | 打开/创建文件 |
11 | sys_close | 6 | 关闭文件 |
12 | sys_dup | 7 | 复制文件描述符 |
13 | sys_pipe | 7 | 创建管道 |
14 | sys_kill | 7 | 发送信号给某进程 |
15 | sys_sigaction | 7 | 设立信号处理例程 |
16 | sys_sigprocmask | 7 | 设置要阻止的信号 |
17 | sys_sigreturn | 7 | 从信号处理例程返回 |
18 | sys_sleep | 8 | 进程休眠一段时间 |
19 | sys_thread_create | 8 | 创建线程 |
20 | sys_gettid | 8 | 获取线程id |
21 | sys_waittid | 8 | 等待线程结束 |
22 | sys_mutex_create | 8 | 创建锁 |
23 | sys_mutex_lock | 8 | 获取锁 |
24 | sys_mutex_unlock | 8 | 释放锁 |
25 | sys_semaphore_create | 8 | 创建信号量 |
26 | sys_semaphore_up | 8 | 减少信号量的计数 |
27 | sys_semaphore_down | 8 | 增加信号量的计数 |
28 | sys_condvar_create | 8 | 创建条件变量 |
29 | sys_condvar_signal | 8 | 唤醒阻塞在条件变量上的线程 |
30 | sys_condvar_wait | 8 | 阻塞与此条件变量关联的当前线程 |
3.操作系统的特征
内存虚拟化
首先来看看内存虚拟化,它可进一步细分为 内存地址虚拟化 和 内存大小虚拟化 。程序员在写应用程序的时候,不用考虑其程序的起始内存地址要放到计算机内存的具体某个位置,而是用字符串符号定义了各种变量和函数,直接在代码中便捷地使用这些符号就行了。这是由于操作系统建立了一个 地址固定 , 空间巨大 的虚拟内存给应用程序来运行,这是 内存虚拟化 。内存虚拟化的核心问题是:采用什么样的方式让虚拟地址和物理地址对应起来,也就是如何将虚拟地址“翻译”成物理地址。
CPU 虚拟化
CPU 虚拟化也是一种 “时间虚拟化”。操作系统给了运行的应用程序一个幻象,即操作系统把时间分成小段,每个应用程序占用其中一小段时间片运行,用完这一时间片后,操作系统会切换到另外一个应用程序,让它运行。由于时间片很短,操作系统的切换开销也很小,应用程序或使用应用程序的用户基本上是看不出的,反而感觉到多个程序各自在独立“并行”执行,从而实现了 CPU虚拟化 。
并发性
异步性
共享性
共享是指多个应用并发运行时,宏观上体现出它们可同时访问同一个资源,即这个资源可被共享。
持久性
操作系统提供了文件系统来从可持久保存的存储介质(磁盘, SSD 等,以后以硬盘来代表)中取数据和代码到内存中,并可以把内存中的数据写回到硬盘上。
发运行时,宏观上体现出它们可同时访问同一个资源,即这个资源可被共享。
持久性
操作系统提供了文件系统来从可持久保存的存储介质(磁盘, SSD 等,以后以硬盘来代表)中取数据和代码到内存中,并可以把内存中的数据写回到硬盘上。