《现代操作系统》笔记
进程与线程
一、进程
- 每一个被启动的进程都有一个启动该进程的用户UID,子进程拥有和父进程一样的UID。
- 用户可以是某个组的成员,每个组也有一个GID
- 在UNIX中的进程将其存储空间划分为三段:正文段(如程序代码)、数据段(如变量)以及堆栈段,数据向上增长而堆栈向下增长
- UNIX系统,只有一个系统调用可以创建新进程:fork
- fork产生的子进程,会和父进程拥有相同的内存映像、同样的环境字符串和同样的打开文件。
- UNIX中,子进程的初始地址空间是父进程的一个副本,但是涉及两个不同的地址空间,
不可写的内存区是共享的,可写的内存是不共享的
- 进程终止的四个原因:1、正常退出(自愿);2、出错退出(自愿);3、严重错误(非自愿);4、被其他进程杀死(非自愿)
- UNIX不会因为进程被杀死,而杀死该进程创建的所有进程
- UNIX中存在进程层次,WINDOWS因为可以将句柄移交给其他进程,因此所有进程的地位都是相同的
- 进程的三种状态:1、运行态(该时刻进程实际占用CPU);2、就绪态(可运行,但是因为其他进程正在运行而暂时停止);3、阻塞态(除非某种外部事件发生:例如shell等待输入,否则进程不能运行)
- 接收到中断信号后,将进程表中的程序计数器、程序状态字等压入堆栈,然后计算机跳转到中断向量所指示的地址(中断向量表共256个中断向量,由硬件定义)
二、线程
- 为什么要用多线程:如果在处理并发类事务时,程序频繁进入阻塞系统调用,让CPU空转,这是很浪费的
- 进程可以理解为将相关的资源集中在一起,进程有保存程序正文和数据以及其他资源的地址空间,这些资源包括打开的文件、子进程、即将发生的定时器、信号处理程序等
- 线程可以理解为真正在CPU上被调度的实体,它包含一个程序计数器、寄存器、堆栈等,
线程必须在某个进程中执行
- 进程拥有自己的地址空间(即可读地址共享,可写地址不共享);线程拥有一样的地址空间
- 每个线程拥有自己的堆栈
- 线程无法像进程一样利用时钟中断强制让出CPU,因此就出现了
yield
- 用户空间实现线程:1、线程切换时不需要陷入内核;2、允许每个进程有自己的调度算法;3、如果一个线程开始运行,则该进程中的其他线程就不能运行
- 互斥量用于线程的互斥,信号线用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别
- 互斥量值只能为0/1,信号量值可以为非负整数
三、进程间通信
1、互斥方案
- 屏蔽中断:不现实,因为中断的权力不应该给用户,而且对多核处理器无效
- 锁变量:类似于monitor原理,但是会出错
- 严格轮换法:类似于自旋锁,不断检查变量
- Perterson算法:enter_region用于进入临界区,里面有一个空方法体的while循环,leave_region用于离开
- TSL指令:锁住内存总线,不同于屏蔽中断,屏蔽中断对多核处理器无效(XCHG与之类似),可以保证“检查-占锁”这一过程的原子性
2、生产者消费者模型
两个进程共享一个公共的固定大小的缓冲区,其中消费者从缓冲区读数据,生产者往缓冲区塞数据
3、信号量
信号量就是在一个叫做互斥区的门口放一个盒子,盒子里面装着固定数量的小球,每个线程过来的时候,都从盒子里面摸走一个小球,然后去互斥区里面浪(?),浪开心了出来的时候,再把小球放回盒子里。如果一个线程走过来一摸盒子,得,一个球都没了,不拿球不让进啊,那就只能站在门口等一个线程出来放回来一个球,再进去。这样由于小球的数量是固定的,那么互斥区里面的最大线程数量就是固定的,不会出现一下进去太多线程把互斥区给挤爆了的情况。这是用信号量做并发量限制。另外一些情况下,小球是一次性的,线程拿走一个进了门,就把小球扔掉了,这样用着用着小球就没了,不过有另外一些线程(一般叫做生产者)会时不时过来往盒子里再放几个球,这样就可以有新的线程(一般叫做消费者)进去了,放一个球进一个线程,这是信号量做同步功能。你截图里的例子就是这个情况,主线程是生产者,通过sem_post往盒子里放小球(信号量加一),而其他线程是消费者,通过sem_wait从盒子里拿小球(信号量减一),如果遇到盒子里一个小球都没有(信号量为0),就会开始等待信号量不为0,然后拿走一个小球(信号量减一)再继续。本质上来说信号量就是那个盒子,以及“摸不到球就不让进”这个机制。
PV原子操作
PV原子操作的具体定义如下:
● P操作:如果有可用的资源(信号量值>0),则此操作所在的进程占用一个资源(此时信号量值减1,进入临界区代码);如果没有可用的资源(信号量值=0),则此操作所在的进程被阻塞直到系统将资源分配给该进程(进入等待队列,一直等到资源轮到该进程)。
● V操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程;如果没有进程等待它,则释放一个资源(即信号量值加1)。
4、互斥量
可以理解为二元信号量
5、管程
Java的互斥锁synchronized关键字就是基于管程,但是只有部分编程语言支持
6、消息传递
即网络传输的思想
7、屏障
屏障的作用是等待多个线程的完成,屏障允许任意线程的等待
8、避免锁:读-复制-更新(RCU)
和Copy-on-write类似
● 读标志
假设一个Reader企图占领一把RCU锁,它是不须要付出不论什么代价的,仅仅须要设置一个标志,让外界知道有Reader在占领这把RCU锁。多个Reader能够共同持有一把RCU锁。
● 写时拷贝
假设有一个Write企图更新RCU锁所