【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程

1.用户级线程的缺点

用户级线程时完全在用户态内存中创建的一个指令序列,及用户级线程的TCB,栈等内容都是创建在用户态中的,操作系统完全不知道当前进程里有多个线程的存在。那么如果一个用户级线程阻塞了,为了确保CPU不空转,操作系统很可能就会切换到另一个进程执行。也就是说,如果一个用户级线程在内核中阻塞了,则这个进程的的所有用户级线程将全部阻塞(该模式下,进程的所有线程,都对应一个内核调度实体(KES),并且内核不知道这个进程有哪些线程。KES无法将其他线程,调度到其他处理器上。该进程(所有的线程)被阻塞,直到本次系统调用(比如I/O)结束。),这就限制了用户级线程的并发程度。从而限制了由并发性带来的计算机效率的提升。

【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第1张图片
因此我们需要一种能让操作系统感知到其存在的线程形式,在一个线程阻塞时,操作系统懂得切换到另一个线程中执行。这就是和内核级线程。

一个线程崩溃将会导致整个进程崩溃
因为所有线程共享进程地址空间,线程之间是完全透明的,一个线程崩溃就说明该线程此时已经出现了不可逆转的错误,该错误极有可能已经破坏掉了或者即将破坏掉进程的地址空间,因此在操作系统眼里看来继续运行其它线程是有很大风险的,因为大家共同运行的基础已经没有了(完好的地址空间),这就是典型的一粒老鼠屎坏了一锅粥。

2.内核级线程

内核级线程就是要让内核态内存和用户态内存合作创建一个指令执行序列,内核级线程的TCB等信息是创建在操作系统内核中的,操作系统通过这些数据结构可以感知和操纵内核级线程。

【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第2张图片
内核级线程非常适合多核处理器的结构。如果计算机中由两个用户级线程,由于操作系统并不知道存在两个线程,所以同一时间只会用其中一个核来执行这两个线程,就算切换了线程也只会用这一个核心执行,导致另一个核心一直是空闲状态的。但是对于两个内核级线程,操作系统就能操纵两个指令执行序列,会将核1和核2分配给这两个的线程,两个核可以实现同时取值-执行。

由于多处理器的多个核心通常要共享存储管理部件(MMU)以及一些缓存等等,对于多个进程来说,反而是不利的,因为进程需要使用自己的地址空间和地址映射表,硬件MMU就是用来查找映射表的硬件,而某些缓存就来暂存一些最近的地址映射结果。所以多个进程反而不适合同时在多个核心上执行。而两个内核级线程使用的是同一个地址空间,MMU,缓存这些本身就是共享的,所以内核级线程非常适合多核心处理器结构。

【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第3张图片
3. 用户级线程,内核级线程,进程三者关系

以下内容摘自李治军《操作系统原理,实现与实践》

【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第4张图片在这里插入图片描述
4. 内核级线程的切换和创建

类似于用户级线程,内核级线程的切换也要完成“TCB切换,栈切换,PC指针切换”这三件事。但是内核级线程的切换需要进入操作系统内核,那么就需要调用int x80中断,同时由于需要保护内核,用户栈和内核栈不能共享,因此内核态线程的TCB需要关联“一套栈”而不是一个栈。
【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第5张图片【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第6张图片
内核态线程切换可以大体分为五个阶段,也就是课上说的“五段论”。
【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第7张图片
这段切换的详细过程在李治军老师的《操作系统原理,实现与实践》P91有描述,这里不再深入阐述。

结合我的理解,概括地说,就是在开始切换线程时调用中断,将用户栈与内核栈进行关联。用户栈的信息存储在内核栈中。然后调用CPU找到对应的TCB,将内核栈存储到TCB中。再调用下一个TCB,通过TCB找到相应的内核栈,再从内核栈的存储信息中找到对应的用户栈位置,最后将用户栈内容读取出来,恢复寄存器中的值和PC指针指向的位置,完成线程的切换。就像老师说的,切换也就是去内核态中“转了一圈”就回来了。

【哈工大李治军操作系统听课笔记】L11,L12. 内核级线程_第8张图片
了解了切换过程后,内核级线程的创建也就是将一个线程初始化成能切换进去的样子,且切换进去会从其入口函数开始执行的样子。详细过程对应书本P93,这里不再阐述。

你可能感兴趣的:(操作系统专栏,操作系统)