# 用户级线程库的实现
## 一、设计目标
本次课程设计的目标是开发一个用户级线程库,功能包括完整的线程创建/删除/joining,互斥锁,条件变量,以及一个基于优先级的调度器。完成此用户级线程库,可以使用该线程库编写多线程的应用,替代 Linux 中的 pthreads.
## 二、线程库的具体内容
使用线程库前首先要调用 uthread_init()。这个函数只执行一次,负责初始化数据结构,比如全局 uthreads 矩阵和 ut_curthr(当前正在执行的线程)。 uthread_init()中有一些特殊的代码,处理当前正在执行的进程的上下文(即调用 uthread_init()的进程),使其成为一个有效的 uthread,并设置 ut_curthr 为该 uthread,这个 uthread 被称为主线程或 0 号线程。所有事情初始化后,可以使用线程 uthread_create()创建线程。
一旦创建好线程,线程库能够调度这些线程。若线程需要暂时 yield 处理器给另一个线程 (仍然是可执行的,即处于就绪态),则需要调用 uthread_yield()。线程可以通过 uthread_block()进入睡眠态,也可以通过 uthread_wake()被唤醒。uthread_switch()函数负责选择另一个线程运行。调度器调度时,采用优先级调度算法,线程优先级可以由 uthread_setprio()设置,数字越大优先级越高,相同优先级的线程则轮流使用 CPU。每个优先级一个队列,相关的数据结构见 uthread_sched.c 中的 runq_table。
Uthreads 中的线程有 6 种状态,定义如下:
```c++
typedefenum{
UT_NO_STATE,/*无效的线程状态*/
UT_ON_CPU,/*线程正在执行*/
UT_RUNNABLE,/*线程可运行,就绪*/
UT_WAIT,/*线程被阻塞*/
UT_ZOMBIE,/*线程处于 zombie 状态,即已结束,但需要回收资源*/
UT_TRANSITION,/*线程处于创建状态*/
UT_JOINABLE,//线程结束时需要一个线程回收其资源
UT_DETACHABLE,//线程结束时,不需要一个线程回收其资源
UT_NUM_THREAD_STATES//线程状态数目
} uthread_state_t;
```
![](https://www.writebug.com/myres/static/uploads/2021/12/13/b1c545121c3266b0194f8ad4d85b724f.writebug)
在 uthreads 中永远不会有多于一个线程同时执行,但线程可被抢占。在 uthreads 中,使用 uthread_makecontext()创建线程的机器上下文。如果需要改变当前正在执行线程,需要调用 uthread_swapcontext(),这使得当前 CPU 上下文被保存,新的上下文被执行。保存的上下文作为 newctx 参数在之后调用 uthread_swapcontext()时被重新执行。
Uthread 中有一个线程称之为 Reaper 线程,也就是 1 号线程,负责清理已结束线程占用的资源。值得注意的是 reaper 并不清理已经结束但还没有 joined 的 non-detached 线程,而是让 uthread_join()去完成。
## 三、实现过程
需要实现的函数如下(更具体的实现思路请看源代码的注释)。
uthread_yield:当前正在运行的线程让出 CPU,线程仍然处于可运行状态,即 UT_RUNNABLE。调用此函数时,当前线程加入到就绪队列,如果当前线程大于系统中已有的最高优先级线程,则直接从 uthread_yield 返回;否则放弃 CPU,转去执行最高优先级的线程。
uthread_wake:唤醒指定的线程,使其可再次被执行(注意:线程有可能已经处于就绪态)。所作的事情:改变状态,将其放入就绪队列。
uthread_setprio:改变指定线程的优先级。注意,如果线程已处于 UT_RUNNABLE 状态(可执行,但没有占有 CPU),则应该改变其优先级队列,如果该指定线程的优先级高于当前调用者,则调用者还要放弃 CPU;如果线程状态为 UT_TRANSITION,则它是一个刚创建的线程(即将第一次被放入就绪队列),将其状态改为 UT_RUNNABLE。成功时返回 1,否则返回 0。
![](https://www.writebug.com/myres/static/uploads/2021/12/13/b2d45e34f3ba7c1a09c1669c434327c2.writebug)
uthread_switch:找到最高优先级的可运行线程,然后使用 uthread_swapcontext()切换到它(注意设置 UT_ON_CPU 线程状态和当前线程)。如果调用线程本身就是最高优先级线程,则切换回调用线程。主要工作:找出系统中优先级最高的线程,并切换(必须要有可执行线程)。
![](https://www.writebug.com/myres/static/uploads/2021/12/13/fd0f88cd47e8d6cfc87853d56fd37fe6.writebug)
uthread_init:这个函数只在用户进程启动时调用一次,用于初始化所有的全局数据结构和变量。这个函数需要设置每一个线程的 ut_state 和 ut_id,简单起见,本系统中选择线程数组的下标作为 ut_id。
uthread_create:创建一个线程执行指定的函数<func>,函数的参数为<arg1>和<arg2>,优先级为<prio>。首先,使用uthread_alloc找到一个有效的id,找不到时,返回合适的错误;然后,为线程分配栈,分配不成功时返回合适的错误;使用uthread_makecontext()创建线程的上下文;按照新发现的线程id,设置uthread_t结构,调用uthread_setprio设置线程的优先级,在<uidp>中返回线程id。不成功时返回0。
uthread_exit:结束当前的线程(注意设置 uthread_t 中的标志)。如果线程是 UT_DETACHABLE,则通过调用 make_reapable()将其放入清理线程(reaper)清理队列并唤醒清理清理线程。如果线程是 UT_JOINABLE,则唤醒等待的线程。然后调用 uthread_switch()切换线程。
![](https://www.writebug.com/myres/static/uploads/2021/12/13/b1419313e55112e4ba486673a8b7700f.writebug)
uthread_join:等待指定的线程结束,如果线程没有结束执行,调用线程需要阻塞,直到线程结束。主要工作:如果要等待的线程还没有结束,则置线程的等待线程为当前线程,线程状态改为 UT_WAIT,切换线程;如果成功地等到了线程结束,则调用 make_reapable 唤醒清理线程 reaper 将其彻底清理。错误条件及对应的 error code 参考 pthread_join 的 manpage。
![](https://www.writebug.com/myres/static/uploads/2021/12/13/3871ee2dc2d39cfe5762c367a306abe1.writebug)
uthread_self:返回当前正在执行的线程的 id。
uthread_alloc:找到一个自由的 uthread_t,返回其 id(uthread_id_t)。
uthread_destroy:清理指定的线程。
uthread_cond_init:初始化指定的条件变量。
uthread_cond_wait:等待指定的条件变量。改变当前线程的状态,释放当前线程占有的锁,并将当前线程放入条件变量的等待队列中,切换线程。
uthread_cond_broadcast:唤醒等待于此条件变量的所有线程。
uthread_cond_signal:唤醒等待于此条件变量的一个线程。
uthread_mtx_init:初始化指定的 mutex。
uthread_mtx_lock:如果没有线程占有该锁,则将锁的拥有者改为当前线程,否则,当前阻塞,让出 CPU。
uthread_mtx_trylock:试图上锁 mutex,得到锁时返回 1,否则返回 0。
uthread_mtx_unlock:释放锁。如果有其他线程在等待该锁,则唤醒它。
## 四、结果分析
![](https://www.writebug.com/myres/static/uploads/2021/12/13/d35baefe462c9acfeb79cdc17c50b21e.writebug)
## 五、课程设计总结
在这次课程设计的过程中,我对线程调度有了更深入的了解;通过查阅 Linux 的源码和文档以及国内外相关论坛和博客,我解决了出现的各种疑惑和不解,对操作系统的原理也有了进一步的掌握;此外,我可以更熟练地使用 GDB 进行调试,能够更高效地理解和解决程序 bug。
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
资源包含文件:课程设计报告word+指导书+源码 本次课程设计的目标是开发一个用户级线程库,功能包括完整的线程创建/删除/joining,互斥锁,条件变量,以及一个基于优先级的调度器。完成此用户级线程库,可以使用该线程库编写多线程的应用,替代 Linux 中的 pthreads. 详细介绍参考:https://biyezuopin.blog.csdn.net/article/details/125518722
资源推荐
资源详情
资源评论
收起资源包目录
基于C语言开发实现的一个用户级线程库.zip (38个子文件)
uthread_ctx.c 1KB
uthread_private.h 491B
uthread_cond.h 565B
README.en.md 951B
uthread_mtx.h 549B
uthread_mtx.c 2KB
test 51KB
课程设计报告.docx 468KB
test.c 2KB
课程设计报告.docx-md
myoutput.md 9KB
myoutput.md.md 8KB
5-b88a48280dd18690ce56499b11e32cd6.png 18KB
3-2e4d58e1a4b356d5b0fe5f824cd9c11a.png 25KB
4-b95714e67b292237e2db92ddaa9ba5f7.png 18KB
7-5070cafb881d499e6a142472cf665c13.png 225KB
6-abda20282c0a73a8b7dfc2847698bd8f.png 23KB
2-929a2b7098d1ea6521ee78d858bb0382.png 138KB
uthread.c 11KB
test.sh 43B
LICENSE 1KB
READMEbefore.md 871B
uthread_ctx.h 1KB
uthread_queue.h 617B
uthread_sched.h 492B
uthread_cond.c 2KB
list.h 4KB
.gitignore 430B
uthread_sched.c 4KB
用户级线程库课程设计指导书(git版).docx 161KB
Makefile 2KB
uthread_bool.h 206B
README.md 7KB
cscope.files 249B
results.txt 6KB
uthread_queue.c 2KB
uthread.h 4KB
.vscode
settings.json 160B
extensions.json 63B
共 38 条
- 1
shejizuopin
- 粉丝: 9627
- 资源: 1288
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
前往页