操作系统的主要作用:
1、对下保护硬件设备,避免受到运行在上面的应用程序误用;
2、对上则通过操作系统这个中介程序屏蔽了底层的操作的复杂性,提供了统一和简单的访问接口;
并发、并行、异步:
并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。操作系统通过引入进程和线程,使得程序能够并发运行。
异步指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。
共享:
系统中的资源可以被多个并发进程共同使用。有两种共享方式:互斥共享和同时共享。互斥共享的资源称为临界资源,例如打印机等,在同一时间只允许一个进程访问,需要用同步机制来实现对临界资源的访问。
虚拟:
虚拟技术把一个物理实体转换为多个逻辑实体。主要有两种虚拟技术:时分复用技术和空分复用技术。
多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。
虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
操作系统基本功能:
1、进程管理:进程控制、进程同步、进程通信、死锁处理、处理机调度等。
2、内存管理:内存分配、地址映射、内存保护与共享、虚拟内存等。
3、文件管理:文件存储空间的管理、目录管理、文件读写管理和保护等。
4、设备管理:完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利
用率。主要包括缓冲管理、设备分配、设备处理、虛拟设备等。
系统调用:
如果一个进程在用户态需要使用内核态的功能,就进行系统调用从而陷入内核,由操作系统代为完成。
中断分类:
1.外中断:由 CPU 执行指令以外的事件引起,如 I/O 完成中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输入/输出请求。此外还有时钟中断、控制台中断等。
2.异常:由CPU执行指令的内部事件引起,如非法操作码、地址越界、算术溢出。
3.陷入:在用户程序中使用系统调用。
进程与线程:
1.进程:进程是资源分配的基本单位。
进程控制块(Process Control Block, PCB)描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。
2.线程:线程是独立调度的基本单位。
一个进程中可以有多个线程,它们共享进程资源。QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP请求线程、事件响应线程、渲染线程等等。
区别:
1、拥有资源:进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
2、调度:线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
3、系统开销:由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
4、通信方面:线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助IPC(Inter-Process Communication)。
进程调度算法:
不同环境调度算法不同
1、批处理系统,没有太多的用户操作,保证吞吐量和周转时间
1.1 先来先服务(FCFS):按照请求的顺序进行调度。
1.2 短作业优先(SJF):按估计运行时间最短的顺序进行调度。
1.3 最短剩余时间优先(SRTN):按估计剩余时间最短的顺序进行调度。
2、交互式系统,大量的用户交互操作,需快速的进行响应
2.1 时间片轮转:所有就绪进程按照FCFS原则排成队列,设定运行时间片
2.2 优先级调度:为每个进程分配一个优先级,按优先级进行调度。
2.3 多级反馈队列:时间片轮转调度算法和优先级调度算法的结合。
3、实时系统:要求一个请求在一个确定时间内得到响应。
分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。
进程同步:
1、临界区:对临界资源进行访问的那段代码称为临界区。
为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
2、同步与互斥 同步:多个进程按一定顺序执行;
互斥:多个进程在同一时刻只有一个进程能进入临界区。
3、信号量:信号量(Semaphore)是一个整型变量,可以对其执行down和up操作,也就是常见的 P 和 V 操作。
down : 如果信号量大于0,执行-1操作;如果信号量等于0,进程睡眠,等待信号量大于0;
up :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。
down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
如果信号量的取值只能为 0或者1,那么就成为了互斥量(Mutex) ,0 表示临界区已经加锁,1 表示临界区解锁。 使用信号量实现生产者-消费者问题
4、管程:使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。
经典同步问题:
1. 读者-写者问题:允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
2. 哲学家进餐问题
进程通信:
进程同步:控制多个进程按一定顺序执行; 进程通信:进程间传输信息。
进程通信是一种手段,而进程同步是一种目的。也可以说,为了能够达到进程同步的目的,需要让进程进行通信,传输一些进程同步所需要的信息。
通信方式:
1、管道:调用pipe函数创建,fd[0] 用于读,fd[1] 用于写。
特点:只能支持半双工;只能在父子进程中使用
2、命名管道(FIFO):去除了管道只能在父子进程中使用的限制。
FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进
程和服务器进程之间传递数据。
3、消息队列:
消息队列可以独立于读写进程存在,从而避免了FIFO中同步管道的打开和关闭时可能产生的困难;
避免了FIFO的同步阻塞问题,不需要进程自己提供同步方法;
读进程可以根据消息类型有选择地接收消息,而不像FIFO那样只能默认地接收。
4、信号量:它是一个计数器,用于为多个进程提供对共享数据对象的访问。
5、共享存储:允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。需要使用信号量用来同步对共享存储的访问。
多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。
6、套接字:与其它通信机制不同的是,它可用于不同机器间的进程通信。
虚拟内存:为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。
为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
分页系统地址映射:
内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表(Page table)存储着页(程序地址空间)和页框(物理内存空间)的映射表。
一个虚拟地址分成两个部分,一部分存储页面号,一部分存储偏移量。
静态链接:
静态链接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
1、符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
2、重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。
动态链接:
静态库有以下两个问题:
当静态库更新时那么整个程序都要重新进行链接;
对于printf这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。
共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows系统上它们被称为 DLL。它具有以下特点:
1、在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
2、在内存中,一个共享库的.text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。