关于操作系统的简单介绍
文章目录
1.什么是操作系统
现代计算机包括:
- 一个或多个处理器(Processor)
- 主内存(Main Memory)
- 磁盘(Disk)
- 打印机(Printer)
- 各种输入/输出设备(IO device)
管理所有这些组件需要一个软件层——也就是操作系统
2.操作系统的类别
主机操作系统(Mainframe OS):
- 在大型计算机上使用的非常强大的系统
- 支持批处理(批量处理)、事务处理和分时处理
- 例子:OS/390, Linux
服务器操作系统(Server OS):
- 提供服务(通常通过网络)、打印服务、文件系统或Web服务的大型PC
- 例子:Solaris, FreeBSD, Linux, Windows Server 200x
多处理器操作系统(Multiporcessor OS):
- 用于多处理器硬件的服务器操作系统的特殊版本
个人电脑操作系统(Personal Computer OS):
- 例子:Window Vista, Linux, FreeBSD, MacOS
掌机操作系统(Handheld Computer OS):
- 例子:Symbian OS, Palm OS, Android, IOS
嵌入式操作系统(Embedded OS):
- 不受信任的软件将不能在嵌入式系统上运行
- 例子:ONX, Vxworks
传感器节点操作系统(Sensor Node OS):
- 例子:TinyOS
实时操作系统(Real-Time OS):
- 实时运行的特殊操作系统
- 硬件响应必须满足严格的时间要求
- 例子:e-Cos
智能卡操作系统(Smart Card OS):
- 在信用卡大小的系统上运行的操作系统
- 主要基于JVM
3.一些概念
每个现代操作系统都提供以下支持:
- 创建和管理流程
- 内存管理
- 持久性存储管理
- 与外设设备通信
- 保护
- 用户接口
3.1 进程(Process)
定义:
- 进程是正在执行的程序
- 进程是程序的运行实例
与每个进程相关联的:
- 进程的地址空间(指令、数据、栈堆)
- 存储在一组寄存器中的值,包括程序计数器(PC)、栈堆指针和其他硬件存储器
- 运行程序所需的其他信息
注意:
- 每个被授权使用OS的人都会被分配一个UID
- 而每个进程都有一个唯一的进程id(PID)
进程表/PCB表:
- 进程控制块(Process Control Block)是操作系统内核中一个数据结构,它包含管理特定进程所需的信息
- OS为每个进程维护一个PCB
- OS跟踪进程表中所有的进程
- 进程表组织形式:
-
链接
-
索引
-
Unix进程的内存映像:
- 文本:程序代码
- 数据:程序数据
- 静态声明的变量
- 由malloc()或new (堆上)分配的区域
- 栈:
- 自动变量
- 过程调用信息
- 地址,包括:
- 文本(不增长的)
- 数据(向上增长)
- 栈堆(向下增长)
进程可以创建其他进程:
- 进程树:
- A创建了两个子进程B和C
- B创建了三个子进程D、E和F
3.2 内存管理(Memory Management)
管理和保护主内存:
- 旧的操作系统:
- 只需根据需要在内存中交换程序即可
- 程序必须比物理内存大一点
- 现代操作系统:
- 允许同时运行多个程序
- 内存被划分为单元,这些单元为每个正在运行的进程保存数据和指令
管理进程地址空间:
- 虚拟内存:不一定是如何在物理的RAM(Random Access Memory)中布局内存
- 地址空间是进程如何看到自己的内存的一个东西:每个进程都有自己独立的地址空间
3.3 文件系统(File System)
文件、目录和文件系统:
- Secondaty Storage在计算机系统中提供持久性存储
- OS实现了一个抽象——文件,用来表示存储在Secondaty Storage上的字节
- 文件被组织成目录
- 目录构成文件系统
- OS提供了在Secondary Storage上的文件、目录、文件系统管理的服务
可以通过扩展Unix文件系统,使其包含来自其他Secondary Stroage设备的文件:
- 挂载前:软盘(Floppy)上的文件无法访问
- 挂载后:软盘上的文件是文件层次结构的一部分
Unix特殊文件:
- 特殊文件:
- 表示硬件或逻辑设备
- 设备驱动(Device Driver)程序接口,它出现在文件系统中,就好像它是一个普通文件一样
- 在名为/dev的目录中找到
- 块特殊文件:/dev/hd1
- 字符特殊文件:
- 用于模拟串行(Serial) IO设备,如键盘和打印机
- 在/dev/lp中
管道(Pipe):
- 提供两个独立进程之间的通信通道
3.4 输入输出(IO)
概述:
- 每个OS都有一个I/O子系统
- OS必须知道如何与多个外设进行通信
- OS必须为I/O设备提供一个接口,使程序员能够执行I/O而不需关心H/W细节
- 现代OS通过设备驱动程序与硬件连接
设备驱动程序(Device Driver):
- 隐藏硬件设备细节的黑盒子
- 主要作用:将标准调用映射到特定于设备的操作(比如在用户态只用write,是为了写文件,设备驱动会把这个标准的write调用映射到用于写文件的特定设备)
- 可以与内核的其余部分分开开发
3.5 保护(Protection)
概述:
- OS必须防止未经授权的资源访问,还必须防止一个用户干扰另一个用户的资源
- OS提供以下机制:
- 决定谁可以进入计算机系统
- 用户可以访问哪些资源
- 用户可以对资源进行什么操作
例子:
- unxi中的文件受到9位二进制保护码的保护:
- 保护码由3位字段组成,一个用于所有者(Owner),一个用于组(Group),一个用于其他(Others)
- 每个字段有一位用于读,一位用于写,一位用于执行,它们被称为rws位
3.6 内核(Kernel) & 实用程序(Utility)
内核(Kernel) :
- 通常是指操作系统中实现基本功能的那部分,并且总是存在于内存中
- 在某些情况下,整个操作系统被创建为一个整体实体,整个单元称为内核
实用程序(Utility):
- 不是操作系统内核的一部分,但与内核紧密合作以提供对系统信息的易用性或访问的程序
- 例如:Shell
3.7 Shell
概述:
- 命令解释器,将输入的文本转换为操作
- 提供用户界面——从用户态获取命令
4.系统调用
概述:
- 应用程序用于从操作系统请求服务的机制
- 系统调用通常使用一种特殊的机器码指令,使处理器改变模式。允许操作系统执行受限制的操作,如访问硬件设备或内存管理单元(MMU)
**例子:**read(fd, buffer, nbytes)
- fd:文件描述符(File Descriptor)
- buffer:读取缓冲区
- nbytes:要读取的字节数
POSIX:
- 便携式操作系统接口(Portable Operating System Interface)
- 一套IEEE标准
- 必选 + 可选部件
- 目标:跨越多个操作系统应用程序的源代码的可移植性
- POSIX过程调用到系统调用的映射不是一对一的
进程管理的系统调用:
调用 | 描述 |
---|---|
pid=fork() | 创建与父进程相同的子进程 |
pid=waitpid(pid, &statloc, options) | 等待子进程终止 |
s=execve(name, argv, environ) | 替换进程的核心映像 |
exit(status) | 终止进程执行并返回状态 |
- fork()
- fork是在POSIX中创建新进程的唯一方法
- 有fork创建的新进程叫子进程
- 这个函数被调用一次,但返回两次
- 子进程返回0,而父进程返回子进程ID,如果错误则返回-1
- 注意:子进程和父进程都将继续执行调用fork之后的指令
- waitpid()
- 正常时返回进程ID,错误时返回0或-1
- pid参数的解释取决于它的值
- pid如果是-1表示等待任何子进程,这时候waitpid等于wait
- pid如果是0表示等待进程号等于pid的子进程
- execve()
- 能够让子进程执行与父进程不同的代码
- exec系列函数(execl, execv, execle, execve)提供了一个设备,用于将新映像覆盖调用进程的进程映像
文件管理的系统调用:
调用 | 描述 |
---|---|
fd=open(file, how, …) | 打开一个文件用于读、写或两者兼用 |
s=close(fd) | 关闭一个文件 |
n=read(fd, buffer, nbytes) | 将数据从文件读取到缓冲区 |
n=write(fd, buffer, nbytes) | 将数据从缓冲区写入文件 |
position=Iseek(fd, offset, whence) | 移动文件指针 |
s=stat(name, &buf) | 获取文件的状态信息 |
目录和文件系统管理的系统调用:
调用 | 描述 |
---|---|
s=mkdir(name, mode) | 创建一个新的目录 |
s=rmdir(name) | 删除一个空目录 |
s=link(name1, name2) | 创建一个新entry——name2指向name1 |
s=unlink(name) | 删除directory entry |
s=umount(special) | 卸载文件系统 |
一些其他的系统调用:
调用 | 描述 |
---|---|
s=child(dirname) | 修改工作目录 |
s=chmod(nam, mode) | 修改文件的保护位 |
s=kill(pid, signal) | 向进程发送信号 |
seconds=time(&seconds) | 获取自1970年1月1日以来经过的时间 |
Win32 API:
- 在windows中,库调用和实际的系统调用是高度解耦的
- 程序员可以使用Win32 API获取操作系统服务
- Win32 API调用的数量非常多,有数千个
- 虽然Win32 API确实是系统调用,但很多数量的API完全是在用户态中执行的
5.操作系统结构
单片系统(Monolithic System)——“the big mess”:
- 所有操作系统操作都放在一个文件中。操作系统是过程(Procedures)的集合,每个过程都可以调用其他过程中的任何一个
- 基本结构:
- 主程序:调用所请求的服务过程
- 执行系统调用的一组服务过程
- 一组帮助服务过程的utility
- 问题:内核组件之间没有相互保护,不容易扩展/修改,结构可能不清楚
分层系统(Layered System):
- OS被分成许多层,每一层都建立在较低的层置上
- 底层是硬件,最高层是带有用户界面的应用程序
- 通过模块化,层的选择使得每个层只使用较低层的功能和服务
- 在每一层封装当前层的信息
微内核(Microkernels):
- 将尽可能多的功能从内核移到用户态
- 操作系统的内核非常小——也就是功能最少
- 原始的内存管理
- IO管理和中断管理
- 进程间的通信(IPC)
- 基本的调度
- 其他由受信任服务在用户态提供操作系统的功能:
- 由内核信任的用户进程提供服务
- 设备驱动程序、文件系统、虚拟内存
- 微内核:
分层系统 vs. 微内核:(从微内核角度论述)
- 用户模块之间使用消息传递进行通信
- 优点:灵活性、可扩展性、可靠性、可移植性
- 缺点:由于用进程间的消息交换替换服务调用而造成的性能开销
客户端-服务器模型(Client-Server Model):
- 微内核的一个细微变化的模型
- 区分两类进程:服务器和客户端
- 将大部分代码向上层移动到更高层,使内核变得最小,并且只负责客户端和服务器之间的通信
- 优点:适合在分布式系统中使用
- 缺点:
- 在用户态执行操作系统功能是困难的
- 有两种方法可以解决这个问题
- 让一些关键进程在内核中运行,可以完全访问硬件,但仍与其他正常进程通信
- 增强内核以提供这些任务,但服务器决定如何使用它
虚拟机(Virtual Machine):
- 硬件之上的虚拟软件层
- 抽象机器的软件仿真
- 给人一种硬件多个实例的错觉
- 支持多操作系统实例
外核(Exokernel):
- 应用程序级资源管理