1:进程
在使用操作系统时,我我们往往需要解决一些事情,那么此时进程就出来了。
进程可以理解成正在运行的一个程序的实例,其也包括程序计数器、寄存器和变量的当前值。
操作系统往往需要在多个进程之间进行切换以完成各种事情。下面是进程切换时,所保存的进程表。
进程的创建方式有:
-
系统初始化(init)
-
正在运行的程序执行了创建进程的系统调用(比如 fork)
-
用户请求创建一个新进程
-
初始化一个批处理工作
进程的结束方式有:
-
正常退出(自愿的)
-
错误退出(自愿的)
-
严重错误(非自愿的)
-
被其他进程杀死(非自愿的)
因为进程可以创建进程,所以进程会有层次结构。
进程的三种基本状态有:
2.线程
首先我们先来说一下为什么要使用多线程。
一般一个进程肯定有一个主线程,主线程是按顺序执行的。如果遇到下面情况,使用多线程是有好处的。
1.遇到阻塞
如果前面的操作发生了阻塞,那么就会影响到后面的操作。这时候可以采用多线程,我感觉就等于是异步调用。以http server为例,如果只用单线程响应HTTP请求,即处理完一条请求,再处理下一条请求的话,CPU会存在大量的闲置时间,因为处理一条请求,经常涉及到RPC、数据库访问、磁盘IO等操作,这些操作的速度比CPU慢很多,而在等待这些响应的时候,CPU却不能去处理新的请求,因此http server的性能就很差 ,此时采用多线程能够明显提高效率。
2.有多核CPU时,且多线程之间没有先后顺序之分
例如计算1-3000之和,我们可以用线程1计算1-1000,线程2计算1001-2000,线程3计算2001-3000,再将3个线程同步,计算其和,则比单线程要快。
下面我们来说说什么是线程:线程我个人理解就是运行在进程中的代码的执行流。是操作系统能够进行运算调度的最小单位。
一个进程中可以并发多个线程,每条线程并行执行不同的任务。
下面是多线程的执行图:
3:关于线程和进程的一些问题
1.怎么理解线程使用而不拥有资源?为什么进程切换的开销比线程切换大呢?
前一句说的不太准确,线程也有自己的资源,比如栈,私有数据等等。说他使用而不拥有资源指的是使用的是进程的打开文件句柄,进程的全局数据,进程的地址空间等等,这些都属于进程,而不属于线程,进程内个线程共享。
进程切换比线程切换开销大是因为进程切换时要切页表,而且往往伴随着页调度,因为进程的数据段代码段要换出去,以便把将要执行的进程的内容换进来。本来进程的内容就是线程的超集。而且线程只需要保存线程的上下文(相关寄存器状态和栈的信息)就好了,动作很小。
2.进程切换与线程切换的区别
进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
3.为什么虚拟地址切换很慢
现在我们已经知道了进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个cache就是TLB,Translation Lookaside Buffer,我们不需要关心这个名字只需要知道TLB本质上就是一个cache,是用来加速页表查找的。由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。