【操作系统笔记5】线程管理

版权声明:QQ: 1063385677 Copyright ©2019 CielleeX 本文地址: https://blog.csdn.net/Ciellee/article/details/89504961

1. 多线程管理

单进程的实现方法: 各个函数之间不是并发进行的,影响资源的使用效率。
多进程的实现方法:各个进程之前的通讯及共享数据。维护进程的开销比较大。
多线程的实现方法:实体之间可以并发的执行 且共享相同的地址空间。

线程: 进程当中的一条流程,由TCB线程控制块来控制,和进程共享堆栈等资源。
优点是:一个进程可以同时存在多个线程;各个线程之间可以并发地执行; 各个线程之间可以共享地址空间和文件资源。
缺点是:一个线程崩溃,会导致所有的线程崩溃,安全可靠得不到保障。

在这里插入图片描述

2. 线程与进程的比较

进程是资源分配单位,线程是CPU调度单位;
进程拥有一个完整的资源平台,而线程只有独享必不可少的资源
线程同样具有就绪态、阻塞态和执行这三种状态,同样具有状态之间的转换关系。

线程的创建时间比进程短;
线程的终止时间比进程短;
同一进程内的线程切换时间比线程短;
由于同一进程的各线程问共享内存和文件资源,可直接进行不通过内核的通信。


3. 线程的实现

①用户线程:用户空间实现, 操作系统看不到,此时CPU调度的单位是进程
缺点:
a. 如果一个线程发起系统调用而阻塞,则整个进程在等待(因为操作系统感知不到线程,只能感知到进程,只会将进程作阻塞,因此所有属于该进程的线程都会随着被阻塞)。
b. 当一个线程开始运行后,除非它主动交出CPU的使用权,否则它所在的进程当中的其它线程将无法运行
c. 由于时间片分配给进程,故与其它进程相比,在多线程执行时,每个线程得到的时间片较少,执行会较慢。

②内核线程:在内核空间实现,操作系统能看到(TCB),此时CPU调度的单位是线程
进程主要是资源的管理,所有属于该进程的线程都被PCB的(TCB list)统一管理。
a. 由内核来维护进程和线程的上下文信息,线程的创建、终止都是通过系统调用/内核函数来实现,切换开销会比较大些
b. 在一个进程,如果某个内核线程发起系统调用而被阻塞,并不会影响其他内核线程运行。
c. 时间片分配给线程,多线程的进程获得更多的CPU运行时间。

③轻量级进程: 在内核中实现,支持用户线程
它是内核支持的用户线程,一个进程可以有一个或多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持。


用户线程和内核线程的对应关系: ①多对一: 多个用户线程对应一个内核线程 ②一对一: 一个用户线程对应一个内核线程 ③多对多: 多个用户线程对应多个内核线程

4.进程的上下文切换(context)

停止当前行进程(从运行状态改变为其他状态)并且调度其他进程(转变成运行状态):
①必须在切换之前存储许多部分的进程上下文
②必须能够在之后恢复他们,所以进程下能显示它曾经被暂停过
③时间上必须快速

需要存储什么上下文?
寄存器(PC、SP、…), CPU状态。
一些时候可能会费时,所以我们应该尽可能的避免。

操作系统为活跃进程准备了进程控制块(PCB)
操作系统将进程控制志(PCB)放置在一个合适的队列里
①就绪队列
②等待 I/O 队列
③僵尸队列

扫描二维码关注公众号,回复: 6104167 查看本文章

5.线统调用exec() 加载程序取代当前运行的进程

a. Exec() 调用允许进程“加载”一个不同的进程并且在main开始执行(事实上是__start开始)
b. 它允许一个进程指定参数的数量(argc)和它的字符串参数数组(argv)
c. 如果调用成功(它是相同的进程,但是调用了不同的程序)
d. 进程本身的 代码,stack(栈) 和 head(堆)均会被重写。

fork() 的执行简单实现: 整体开销昂贵
a. 对子进程分配内存
b. 复制父进程的内存和CPU 寄存器到子进程

在99%的情况里,我们在调用fork() 之后会调用exec(): 开销高
a. 在fork() 操作中内存复制是没有作用的。
b. 子进程可能关闭打开的文件和连接
c. 如果立即执行 exec ,会导致 fork 的内存拷贝是多余的。

vfork()
a. 一个创建进程的系统调用,不需要创建一个同样的内存映像。
b. 一些时候称为轻量级fork()
c. 子进程应该几乎立即调用exec()
d. 现在不再使用,如果我们使用copy on write(COW)技术


如下图中, 如果exec('calc')执行成功的话,子进程的 why would i execute 是无法打印出来的; 如果exec('calc')执行失败的话,子进程会继续运行。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190429125344761.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NpZWxsZWU=,size_16,color_FFFFFF,t_70) #### 5.等待进程的终止和结束 wiat() 系统调用是 父进程用来等待子进程的结束。 a. 一个子进程向父进程返回一个值,所以父进程必须接受这个值并且处理。 b. wait() 系统调用担任这个要求 c. 进程终止是最终的垃圾回收。

僵尸态进程 bombie: 父进程已经死亡的子进程
在这里插入图片描述

最早的 init 进程会 定时的扫瞄所有的进程控制块的列表,看是否有父进程已经死亡的进程,如果有,init 进程会代替父进程对该进程进行回收。

猜你喜欢

转载自blog.csdn.net/Ciellee/article/details/89504961
今日推荐