操作系统01——进程和线程1

150 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

进程是系统中一个正在运行的程序实体,是资源分配的基本单位和独立运行的基本单位。

线程是进程中运行的实际工作单位,是一个进程内可调度的实体,是CPU调度的最小单位。

协程是一种用户态轻量级线程,拥有自己的寄存器上下文和栈,协程的调度完全由用户控制调度切换时,将寄存器上下文和栈保存到其他 地方,在切回来时会恢复先前的寄存器上下文和栈,上下文的切换非常快。

区别

进程和线程有什么区别?

  • 进程是系统进行资源分配和运行调度的基本单位,线程是系统进行资源分配和运行调度的最小单位
  • 进程是线程的容器,一个进程可以并发多个线程,并发的多个线程共享进程的资源。
  • 进程有自己独立的地址空间线程共享所属进程的地址空间
  • 进程切换的开销远大于线程切换的开销;

协程和线程有什么区别?

  1. 线程或进程都可以拥有多个协程

  2. 线程、进程是同步机制,而协程是异步机制

  3. 协程能保留上一次调用时的状态,每次重入都会进入上一次调用的状态

  4. 线程是抢占式,而协程是非抢占式的,需要用户自己切换到其他协程,同一时间只有一个协程可以运行

  5. 线程被分割的CPU资源, 协程组织好的代码流程

  6. 协程需要线程承载运行, 线程是协程的资源,协程利用的执行器(Interceptor)使用线程

线程独占哪些资源?

  • 线程ID
  • 线程自身的栈(堆是共享的)
  • 寄存器

同一进程中的线程可以共享哪些数据?

  • 进程代码段
  • 进程的公有数据(全局变量、静态变量...)
  • 进程的当前目录
  • 进程ID与进程组ID
  • 进程打开的文件描述符
  • 信号处理器/信号处理函数:对收到的信号的处理方式

通信与同步

临界资源和临界区的概念?

临界资源不能被多个进程同时访问的共享资源。当有进程在 使用临界资源时,其他进程必须等待占用进程释放该共享资源才可重新竞争共享资源

临界区是各个进程对临界资源进行操作的程序片段

同步与互斥的概念?

  • 同步多个进程合作时,执行需要有先后顺序。比如这个进程需要另一个进程提供的消息,获得消息之前这个进程进入阻塞态;

  • 互斥多个进程在同一时刻只有一个进程能进入临界区

并发、并行、异步的区别?

并发:在一个时间段同时有多个程序运行。微观上只有一个程序在CPU上运行,宏观上的并发是通过不断的切换实现的;

并行(和串行相比):在多CPU系统中,多个程序无论宏观还是微观上都是同时执行的。

异步(和同步相比):同步是顺序执行,异步是在等待某个资源时可以继续执行

多线程:并发运行的一段代码,是实现异步执行的手段。

如何同步

进程间同步:信号量(互斥量)、管道、消息队列共享内存

线程间同步:信号量(互斥量)、条件变量、读写锁、自旋锁、临界区

进程通信——管道

IPC定义:是进程间通信或者跨进程通信指两个进程之间进行数据交换的过程

管道一种最基本的IPC机制,作用于关系密切的进程之间,完成数据传递。调用pipe系统函数即可 创建一个管道。有如下特质:

  1. 其本质是一个伪文件(实为内核缓冲区)
  2. 由两个文件描述符引用,一个表示读端,一个表示写端。
  3. 规定数据从管道的写端流入管道,从读端流出。

管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区实现

管道的局限性

  1. 数据自己读不能自己写。
  2. 数据一旦被读走,便不在管道中存在,不可反复读取。
  3. 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
  4. 只能在有公共祖先的进程间使用管道。

进程同步问题——管程

进程的同步是目的,而进程间通信是实现进程同步的手段

管程是共享资源的数据结构,将共享变量以及对共享变量的操作进行封装,形成具有一定接口的功能模块只能通过管程提供的某个过程才能访问管程中的资源进程只能互斥地使用管程,使用完之后必须释放管程并唤醒入口等待队列中的进程

HOARE管程

当一个进程试图进入管程时,会在入口等待队列中等待。

wait操作:执行wait操作的进程进入条件变量链末尾唤醒入口等待队列或紧急等待队列中的进程

signal操作:执行signal操作的进程进入紧急等待队列唤醒条件变量链中的进程,若条件变量链为空,则继续执行。

MESA管程:将HOARE中的signal换成了notify(或者broadcast)通知所有满足条件的进程,只进行通知而不是立马交换管程的使用权,在合适的时候,条件队列首位的进程可以进入,进入之前必须用while检查条件是否合适。优点:没有额外的进程切换

生产者-消费者问题

问题描述:使用一个缓冲区来存放数据,通过互斥量控制访问,只有缓冲区没有满时生产者才可以写入数据;只有缓冲区不为空时消费者才可以读出数据

 // 伪代码描述 
 // 定义信号量 full记录缓冲区物品数量 empty代表缓冲区空位数量 mutex为互斥量
 semaphore full = 0, empty = n, mutex = 1;
 ​
 // 生产者进程
 void producer(){
     do{
       P(empty);//检查是否有空位,没有则等待
       P(mutex);//检查互斥量是否可用,不可用则等待
 ​
 // 生产者进行生产
 ​
       V(mutex);//释放互斥量
       V(full);//通知消费者有物品
     } while(1);
 }
 ​
 void consumer(){
     do{
       P(full);//检查是否有物品,没有则等待
       P(mutex);//检查互斥量是否可用,不可用则等待
 ​
     // 消费者进行消费
 ​
       V(mutex);//释放互斥量
       V(empty);//通知生产者有空位
     } while(1);
 }