date | comments | categories | tags | permalink | title | description | ||||
---|---|---|---|---|---|---|---|---|---|---|
2020/2/20
|
true
|
|
|
3.7
|
用户级线程
|
多个进程是如何切换的
|
线程的本质: 指令切换,不切换映射表(进程代码,进程数据,进程资源),效率更高。实质就是映射表不变,只是PC指针改变。
多个执行序列+一个地址空间是否实用?
举例说明:一个显示网页的浏览器,在我们打开一个地址的时候发生了什么?
1、一个线程用来从服务器接收数据
2、一个线程用来显示文本
3、一个线程用来处理图片(如解压缩)
4、一个线程用来显示图片
如果是线性执行,给用户带来的体验就非常不好。
这些线程要共享资源吗?
以上面的浏览器的例子来说明,比如浏览器从数据服务器接收的数据(假设)存放在0x00100处(写),显示的时候需要从这里读出来(度)。
其核心是Yield...
void Yield(){
TCB2.esp=esp;
esp=TCB1.esp;
...
}
TCB:Thread control block,全局数据结构,在执行yield的时候只是切换到要执行的线程栈。
如上图中,刚开始执行到A,遇到B函数调用,把B函数的返回地址104压栈(A自己的栈),jump到B函数中执行,在
B函数中遇到Yield函数,把Yield返回地址压栈(还是A的栈),然后切换到C的TCB,开始向下执行,遇到D函数调用,把D函数的返回地址压栈(C自己的栈),继续执行D函数,遇到Yield,把Yield的返回地址压栈(C自己的栈),再切换到A的TCB,此时弹出栈(A的栈),也就是B函数中的Yield的返回地址204。
总之,就是两个线程就有两个TCB,两个栈,切换的PC在栈中。
用户级线程也是就采用yield()进行切换,这个线程可以由我们自己的代码控制,不用到内核中。
也就是说用户级线程可以自己实现调度,不需要内核。
优缺点:
优点
线程的调度不需要内核直接参与,控制简单。 可以在不支持线程的操作系统中实现。 同一进程中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起,可以节约更多的系统资源。 缺点
一个用户级线程的阻塞将会引起整个进程的阻塞。 用户级线程不能利用系统的多核处理,仅有一个用户级线程可以被执行。会浪费多核的价值