操作系统之线程!
操作系统之线程!
月伴飞鱼并发(Concurrent)
并发是一个CPU处理器同时处理多个线程任务。
宏观上是同时处理多个任务,微观上其实是CPU在多个线程之间快速的交替执行CPU把运行时间划分成若干个(微小)时间段。
- 公平的分配给各个线程执行,在一个时间段的线程运行时,其他线程处于挂起状态,这种就称之为并发。
并行(Parallel)
并行是多个CPU处理器同时处理多个线程任务。
当一个CPU执行一个线程时,另一个CPU可以执行另一个线程。
- 两个线程互不抢占CPU资源,可以同时进行,这就被称之为并行。
同步异步/阻塞非阻塞
当一个request发送出去以后,会得到一个response,这整个过程就是一个同步调用的过程。
- 哪怕response为空,或者response的返回特别快,但是针对这一次请求而言就是一个同步的调用。
当一个request发送出去以后,没有得到想要的response,而是通过后面的callback、状态或者通知的方式获得结果。
异步请求分两步:
- 调用方发送request没有返回对应的response(可能是一个空的response)。
- 服务提供方将response处理完成以后通过callback的方式通知调用方。
阻塞和非阻塞:
- 阻塞和非阻塞就看调用方在发送请求后是否block住了。
协程
协程是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理。
- 而完全是由程序所控制(也就是在用户态执行)。
这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。
用户态和内核态
Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。
按照权限管理的原则,多数应用程序应该运行在最小权限下。
因此,很多操作系统,将内存分成了两个区域:
- 内核空间(Kernal Space),这个空间只有内核程序可以访问。
- 用户空间(User Space),这部分内存专门给应用程序使用。
用户空间中的代码被限制了只能使用一个局部的内存空间,我们说这些程序在用户态(User Mode) 执行。
内核空间中的代码可以访问所有内存,我们称这些程序在内核态(Kernal Mode) 执行。
什么情况会导致用户态到内核态切换:
系统调用:
用户态进程主动切换到内核态的方式,用户态进程通过系统调用向操作系统申请资源完成工作。
- 例如 fork()就是一个创建新进程的系统调用。
异常:
当 CPU 在执行用户态的进程时,发生了一些没有预知的异常。
这时当前运行进程会切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常。
中断:
当 CPU 在执行用户态的进程时,外围设备完成用户请求的操作后,会向 CPU 发出相应的中断信号。
- 这时 CPU 会暂停执行下一条即将要执行的指令,转到与中断信号对应的处理程序去执行,也就是切换到了内核态。
如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后边的操作等。
用户态和内核态切换的开销
保留用户态现场(上下文、寄存器、用户栈等)
复制用户态参数,用户栈切到内核栈,进入内核态
额外的检查(因为内核代码对用户不信任)
执行内核态代码
复制内核态代码执行结果,回到用户态
恢复用户态现场(上下文、寄存器、用户栈等)
异常和中断的区别
中断是由硬件设备产生的,而它们从物理上说就是电信号,之后它们通过中断控制器发送给CPU。
接着CPU判断收到的中断来自于哪个硬件设备(这定义在内核中)。
- 最后,由CPU发送给内核,有内核处理中断。
异常是由CPU产生的,同时,它会发送给内核,要求内核处理这些异常。
系统调用过程:
如果用户态程序需要执行系统调用,就需要切换到内核态执行。
内核程序执行在内核态(Kernal Mode),用户程序执行在用户态(User Mode)。
当发生系统调用时,用户态的程序发起系统调用。
因为系统调用中牵扯特权指令,用户态程序权限不足,因此会中断执行,也就是 Trap(Trap 是一种中断)。
发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序。
内核程序开始执行,也就是开始处理系统调用。
内核处理完成后,主动触发 Trap,这样会再次发生中断,切换回用户态工作。
线程调度算法
先到先服务(First Come First Service,FCFS)
就是先到的作业先被计算,后到的作业,排队进行。
最短作业优先
最短作业优先(Shortest Job First, SJF)调度算法通常会同时考虑到来顺序和作业预估时间的长短。
优先级队列(PriorityQueue)
优先级队列可以给队列中每个元素一个优先级,优先级越高的任务就会被先执行。
抢占(Preemption)
抢占就是把执行能力分时,分成时间片段。
让每个任务都执行一个时间片段。
如果在时间片段内,任务完成,那么就调度下一个任务。
- 如果任务没有执行完成,则中断任务,让任务重新排队,调度下一个任务。
多级队列模型:
多级队列,就是多个队列执行调度。
紧急任务仍然走高优队列,非抢占执行。
普通任务先放到优先级仅次于高优任务的队列中,并且只分配很小的时间片。
如果没有执行完成,说明任务不是很短,就将任务下调一层。
下面一层,最低优先级的队列中时间片很大,长任务就有更大的时间片可以用。
通过这种方式,短任务会在更高优先级的队列中执行完成,长任务优先级会下调,也就类似实现了最短作业优先的问题。