一 概述

定义

操作系统是管理计算机硬件的程序

同时是软件的控制基础

还是计算机用户和计算机硬件的中间层

设计出来的目的是为了执行用户程序、使他们更加方便地解决问题,让计算机系统更加便于使用

  • 资源分配器
  • 控制程序(程序执行和I\O操作)
  • 内核(一直运行)

驱动方式

操作系统由中断驱动

外部的中断主要是外设发出的中断请求,如IO等

内部中断通常是不可预料的系统错误等,这类错误通常不可避免

计算机系统架构

  • 单核
  • 多核
  • 集群

操作系统结构

多道程序设计 multiprogramming

  • 允许多个进程任务同时在内存中,由CPU决定运行哪个进程,完成哪个任务
  • 这样做可以减少CPU的空闲时间,提高系统效率
  • 需要作业调度机制进行道的分配

作业调度:把磁盘中的程序调入内存,准备执行

多道设计中系统需要的特性

  • IO读写周期由系统决定
  • 内存分配由系统决定
  • CPU计划进程的执行
  • 设备的调度

分时 timesharing

CPU执行一个进程一个时间片后,根据特定的标识,会选择一个进程开始执行。这种不断切换执行过于频繁,导致可以认为是同时多个进程在进行,需要进程调度

进程调度:决定当前哪个进程在CPU上执行

实时 real-time

实时操作系统是相对于分时操作系统的一个概念。

在一个分时操作系统中,计算机资源会被平均地分配给系统内所有的工作,各项任务需要花多长时间来完成,这一点并不重要;

而在一个实时操作系统之中,最关注的是每个任务在多长时间内可以完成。简单地说,实时和分时操作系统最大的不同在于 “时限(deadline)”这个概念。

批处理系统 batch os

早期的一种大型机用操作系统。可对用户作业成批处理,期间无需用户干预,分为单道批处理系统和多道批处理系统

批处理系统提高工作效率,而分时系统提高人机交互效率


进程调度

进程是一个程序的执行状态

是一个动态实体,需要资源进行它的任务

CPU、IO、内存、数据

操作系统与进程的关系

  • 创建、删除进程
  • 暂停、恢复进程
  • 为进程的同步、通信和死锁提供解决机制

二 操作系统结构体系

系统调用

操作系统提供了一个接口,即系统调用,允许用户程序通过接口与操作系统进行交互

  • 进程控制
  • 文件管理
  • 设备管理
  • 通信
  • 系统信息获得

通信

进程管理内存,不同进程间内存不能互相访问,需要通过共享内存或消息传递来进行信息交换

程序和操作系统之间如何传递参数?

  • 消息传递
  • 共享内存

引导程序

初始引导过程主要由计算机的BIOS完成。BIOS是固化在ROM中的基本输入输出系统(Basic Input/Output System),其内容存储在主板ROM芯片中,主要功能是为内核运作环境进行预先检测。

其功能主要包括中断服务程序、系统设置程序、上电自检和系统启动自举程序等

BIOS(Basic Input-Output System)基本输入输出系统,其内容集成在微机主板上的一个ROM芯片上,主要保存着有关微机系统最重要的基本输入输出程序,系统信息设置、开机上电自检程序和系统启动自举程序等。

微机部件配置记录是放在一块可读写的 CMOS RAM 芯片中的,主要保存着系统基本情况、CPU特性、软硬盘驱动器、显示器、键盘等部件的信息。

CMOS RAM芯片由系统通过一块后备电池供电,无论是在关机状态中,还是遇到系统掉电情况,CMOS信息都不会丢失。

在 BIOS ROM芯片中装有"系统设置程序",主要用来设置CMOS RAM中的各项参数


三 进程

进程的定义与构成

进程是一段运行中的程序

包含以下几方面

  • 堆栈
  • 程序计数器PC
  • 数据

进程的状态与转换

image-20230920084311751

  • new 进程被创建

  • running 进程正在运行

    通过时钟中断(时间片)改变状态到ready态

  • waiting 进程正在等待

    从等待态也可以直接转换到终止态

  • ready 进程就绪

  • terminated 进程终止

从等待态waiting回到就绪态ready,需要发出I/O中断信号

进程调度队列

  • 工作队列
  • 准备队列
  • 设备队列

进程可以在已有的队列中不断转移

上下文切换 Context Switch

需要硬件支持

切换需要保存旧进程状态,载入新进程状态

切换时间是经常性开支(浪费),系统切换时无法工作

调度 schedulers

长期调度程序(进程调度)

不会很频繁地被唤起

控制多道程序的道数

短期调度程序(CPU调度)

会很频繁地被唤起

控制CPU调入哪一个进程

父子进程、进程的创建、等待与停止

父进程创建(linux中是fork)子进程,以此下去会形成一个进程树

资源共享

有三类情况

  • 父子进程共享全部资源
  • 父进程共享一部分资源给子进程
  • 父子进程不共享资源

执行(exec)

  • 父子进程同时执行
  • 父进程等待子进程结束(wait),或父进程主动停止子进程(abort)
  • 父进程结束时,若还存在活动子进程也需要结束(子进程不能脱离父进程单独存在)

地址空间

  • 子进程复制父进程的地址空间
  • 子进程有一段程序进行地址空间的加载

具体代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<cstdio>
#include <sys/types.h>

void main(int argc, char *argv[]) {
pid_t pid;
pid=fork();
if (pid<0) { /* error occurred */
fprientf(stderr, “Fork failed”); exit(1)
}
else if (pid==0) { /* child process */
exec(“/bin/ls”, “ls”, null);
}
else { /* parent process */
wait(null);
printf(“Child Complete”); exit(0);
}
}

// 需要注意的是,父子进程的先后执行顺序没有规定,父子进程的输出结果可能会存在多种次序

windows下使用CreateProcess()作为fork()的替代,WaitForSingleObject()作为wait()的替代

独立进程与协作进程

独立进程(Independent process)不能影响其他进程的执行,也不能被其他进程影响

而协作进程可以影响和被影响

  • 信息分享
  • 提高速度
  • 模块化
  • 方便

进程间通信 Interprocess Communication

进程的通信需要消息系统

send - 发送 (固定尺寸大小/可变大小)

receive 接收

两个进程要通信,需要建立之间的连通信接后交换消息

能中断通信链接的有物理中断和逻辑中断

通信方式

  • 消息队列
  • 共享内存

消息队列系统

两个操作原语可以用于消息队列系统

send(process_name,message)

receive(process_name,message)

原语 Primitives

执行过程不可中断

命名 naming

两个进程的直接通信,可以给进程命名(symmetry)以区分进程,也可以不命名(asymmetry)而改用序号id的方式区分进程,但两者都有缺点,即更改命名会造成原进程的目标丢失

消息盒 mailbox

两个进程可以通过消息盒实现间接通信

同步 Synchronization

阻塞Blocking - 同步Synchronization

非阻塞Non-blocking - 异步asynchronous

发送和接收原语可能是阻塞的,也可能是非阻塞的

阻塞发送意味着发送方必须等到已发送消息被对方接收才能继续下一次发送,阻塞接收同理,此时生产者 - 消费者问题将不会发生

缓冲区

无界缓冲区 - 理论上可能,实际上不可能

有界缓冲区 - 如果满了就需要等待


共享内存系统

多个进程之间共享一段内存段,进程可以通过读写这一段内存段以实现消息的通信。

但是,数据的形式和位置由进程决定而不由操作系统决定,这会带来一些问题。

生产者 - 消费者问题

对无界的缓冲区,不需要考虑

对有界的缓冲区,生产者生产的信息会被消费者消费,这会带来一些问题,如生产者生产信息导致缓冲区溢出,或消费者在没有信息的缓冲区中消费。要求正确的完成生产者 - 消费者问题,需要共享内存中一些操作的实现。

有界的缓冲区可以看成是一个环形的缓冲圈,设置inout指针,指代生产位置与消费位置

1
2
3
4
5
6
7
8
9
10
11
#define BUFFER_SIZE 10
Typedef struct {
. ..
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
// in: 当前要生产的位置
// out: 当前要消费的位置
// in = out 表示缓冲区为空
// ((in + 1) % BUFFER_SIZE) = out 表示缓冲区已满

生产者:

1
2
3
4
5
6
7
8
9
10
item next produced;
while (true) {
/* produce an item in next produced */
while (((in + 1) % BUFFER SIZE) == out) {
// buffer is full, do nothing
}

buffer[in] = next produced;
in = (in + 1) % BUFFER SIZE;
}

消费者:

1
2
3
4
5
6
7
8
9
item next consumed;
while (true) {
while (in == out) {
/* buffer is empty, do nothing */
}
next consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
/* consume the item in next consumed */
}

可以看出,这个缓冲区的缓冲空间实际上只有BUFFERSIZE - 1,因为in与out指针重叠已经代表缓冲区为空

进程与操作系统间的通信方式

3种常用方式用于在运行程序和操作系统之间的参数传递

  • 寄存器中的参数传递
  • 参数存在内存的一张表中,表地址作为寄存器的参数传递
  • 程序把参数压入栈,由操作系统弹出

总结:进程间的通信方式

  • 共享内存

    能够很容易控制容量,速度快,但无法自动同步。所以需要额外保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题

  • 消息队列

    容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题

  • 管道通信

    无名管道Pipe: 速度慢,容量有限,只有父子进程能通讯

    命名管道FIFO:FIFO可以在无关的进程之间交换数据,与无名管道不同。FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统

  • socket

  • 信号量

    不能传递复杂消息,只能用来同步

  • 进程通信

    直接通信

    非直接通信:mailbox


四 线程

定义

线程是CPU能利用的最基本单元

与进程类似,它同样包括:

  • 程序计数器PC
  • 线程编号id
  • 寄存器集

共享量

线程会与同个进程下的其他线程共享

  • 相同的代码段
  • 相同的数据段
  • 其他相同的操作系统资源,比如打开的文件和信号

单线程进程与多线程进程

一些重要的系统进程只允许单一线程的创建与保持,称这种进程为单线程进程

现在的操作系统大多支持多线程进程

多线程的优势

  • 高反应性

    可以快速反应,响应性能高

  • 资源共享

    不需要诸如进程的共享内存和消息队列,线程天然共享进程的操作系统资源,一个应用可以同时在同一个地址空间应用多线程,以利用代码和数据

  • 更加经济实惠

    创建进程开销大,而创建线程开销更小,更加经济实惠

  • 可扩展性强

    多处理器体系结构的利用 Utilization of MP Architectures

    若为多进程处理器架构的操作系统,多线程可以在多个进程核心上平行运行,提高性能

多线程模型

指的是用户线程内核线程

多对一模型 Many to One

早期Java使用的就是多对一模型,并不需要操作系统,而是只需要Java虚拟机

不支持内核线程的系统通常使用多对一模型

一对一模型 One to One

现在的windows,linux都支持

多对多模型 Many to Many

多对多没有要求用户线程数等于内核线程数

操作系统下的线程

PThread

UNIX系统通用的线程标准,是一种POSIX标准的API库

使用

  • pthread_create()创建线程
  • pthread_join()等待线程结束
  • pthread_exit()退出线程

Windows XP Thread

一对一模型

每个线程包含

  • 线程id
  • 寄存器集合
  • 分开的用户栈和内核栈
  • 私有数据存储空间

一般来说,以上的内容被称为线程的上下文

使用

  • CreateThread() 创建线程
  • WaitForSingleObject()WaitForMultipleObjects()等待线程
  • CloseHandle()结束线程

Linux Thread

Linux一般称线程为task(任务)

使用clone()创建线程,同时可以共享父进程的地址空间

Java Thread

Java线程通过JVM管理

可以通过继承Thread类或实现Runnable接口实现

屏幕快照 2023-10-20 23.29.25

进程和线程:概念、区别与联系

概念

进程是一个具有独立功能的程序关于某个数据集合的依次运行活动。 是系统进行资源分配和调度的独立单位,也是基本的执行单元。是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动。

进程结构特征: 由程序、数据和进程控制块三部分组成。具有 独立性、并发性、异步性和动态性的特点。

进程的概念主要有两点:

  • **进程是一个实体。**每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)–存储处理器执行的代码,数据区域(data region)–存储程序执行期间的一些数据变量,堆栈(stack region)–存储动态分配的内存和本地变量及指令。

  • **进程是一个“执行中的程序”。**程序是一个没有生命的实体,只有在运行时处理器才会赋予它生命,才能成为一个活动的实体,我们称其为“进程”。

每一个进程都会有一个独一无二的编号,被称为进程标识码,简称PID

进程优点

  • 进程之间相互独立,可以并行执行不同的任务,有更好的安全性和稳定性

进程缺点

  • 进程之间的通信和协作较为困难,进程切换开销较大,需要消耗更多的系统资源

线程是进程中的 执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源( 程序计数器,一组寄存器和栈),但它可与同属一个进程的其他线程 共享进程所拥有的全部资源

线程优点

  • 易于调度。
  • 提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一个程序的不同部分。
  • 开销少。创建线程比创建进程要快,所需开销少,占用的资源也少;
  • 充分发挥多处理器的功能。通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分的运行
  • 线程之间的通信和协作更加方便,线程切换开销较小,可以更高效地利用系统资源

线程缺点

  • 线程之间共享相同的内存空间,容易出现数据竞争和同步问题,需要使用锁、信号量等机制来解决
  • 同时,一个线程出现错误可能会影响整个进程的稳定性

进程与线程的区别

  • 调度:线程作为处理器调度和分配的基本单位,而进程是作为拥有资源的基本单位

  • 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行

  • 拥有资源:进程是拥有资源的一个独立单位,有自己独立的地址空间;线程不拥有系统资源,但可以访问隶属于进程的资源,共享进程的地址空间、内存空间、地址空间、文件句柄等资源;从概念上来说,进程是一个容器,而线程则是容器内的执行单元

  • 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销

进程和线程的关系

  • 二者均可并发执行.

  • 线程是指进程内的一个执行单元,也是进程内的可调度实体。一个程序至少有一个进程,一个进程至少有一个线程,一个线程只属于一个进程.

  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

  • 处理机分给线程,即真正在处理机上运行的是线程。

  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。而线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。