操作系统笔记

进程

是应用程序执行副本,操作系统资源分配最小单位

进程有很多东西,但是我们执行只需要CPU和内存(程序编译成2进制存入内存,然后CPU去读取内存中的指令一条条执行,不需要进程),于是抽象出了线程
应用启动就变成进程,进程会先拿到一个主线程,这个主线程再去操作系统申请线程

线程

OS分配执行程序的最小单位(执行程序指的kernal thread,应用程序的thread 和kernal thread存在映射关系);只需要程序和CPU;所有的进程启动以后必然有一个主线程。

(1)real thread

用户实在自己的空间创建线程,而OS只调度自己的线程,所以用户的线程需要挂靠/映射到OS的线程中,因为这样才能真的执行。所以只有kernal thread才是真的thread。

(2)进程线程区别

进程是拿资源的,线程是执行程序的,他俩关联性可以不强。

(3)Thread pool

高并发场景下的思想:

(4)线程切换

阻塞状态是由操作系统内核来进行切换:要存储当前线程的cpu状态,进入调度器,调度完又加载CPU状态;
如果任务很小,这样线程频繁切换,很不划算,于是想到了将所有task抽象成更小的模型:routine

(5)线程的几种可用状态

1.创建(new)

建立一个新线程,新生的线程将处于新建状态。此时它已经有了相应的主存空间和其他资源,并已经被初始化。

2.准备(runnable)

线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3.阻塞状态(blocked)

阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:

  1. 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
  2. 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
  3. 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

4.运行状态(running)

可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

5.死亡状态(dead)

线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

协程

比线程更小,协程的暂停完全由程序控制(也就是在用户态执行)。
Routine的一种实现(轻量级线程)

高IO,任务很多的情况下创建routine,切换成本更低,是轻量级线程。

并发和并行

1.并发

指宏观上在一段时间内能同时运行多个程序
OS通过引入进程和线程,使得程序能够并发运行

2.并行

指同一时刻能运行多个指令。
需要硬件支持,如多流水线、多核处理器或者分布式计算系统。

共享

共享是指系统中的资源可以被多个并发进程共同使用。
有两种共享方式:互斥共享同时共享

死锁

并发进程在竞争资源的过程中可能产生死锁。

产生原因

根本原因:系统能够提供的资源个数比请求该资源的进程数要少。当系统中两个或多个进程因申请资源得不到满足而等待时,若各进程都没有能力进一步执行,系统就发生死锁。

产生条件

(1)互斥

多进程共享的资源具有互斥特性,即一次只能由一个进程使用。如果另一个进程申请该资源,那么申请进程必须等待,直到该资源被释放。

(2)不剥夺(非抢占)

进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

(3)占有并等待(部分分配)

进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

(4)环路条件(循环等待)

存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。

处理方法

  1. 预防死锁
  2. 避免死锁
    有序资源分配法
    银行家算法
  3. 死锁检测与忽略

如何确保N个线程可以访问N个资源同时又不导致死锁?

只要破坏四个必要条件其中任意一个条件,就可以避免死锁,其中最简单的就是破环循环等待条件。指定获取锁的顺序,并强制线程按照指定的顺序获取锁,按同一顺序访问对象,加载锁,释放锁。

进程通信方式

进程通信是一个进程与另一个进程间共享信息的一种方式。

1.消息队列

(1)消息缓冲通信

(2)信箱通信

2.共享内存

eg.复制粘贴板
最快的一种通信方式,多个进程可同时访问同一片内存空间,相对其他方式来说具有更少的数据拷贝,效率较高。

*3.管道通信

无名管道(PIPE)

系统内核,FIFO

有名管道(MKPIPE)

缓存

4.信号量

5.套接字(SOCKET)

常见的进程调度算法


虚拟

大内核和微内核

中断分类

1.外中断

2.异常

3.陷入