当前位置:网站首页>基于C语言开发实现的一个用户级线程库
基于C语言开发实现的一个用户级线程库
2022-06-29 16:43:00 【biyezuopinvip】
资源下载地址:https://download.csdn.net/download/sheziqiong/85821835
资源下载地址:https://download.csdn.net/download/sheziqiong/85821835
用户级线程库的实现
一、线程库的具体内容
使用线程库前首先要调用 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 种状态,定义如下:
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;

在 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。

uthread_switch:找到最高优先级的可运行线程,然后使用 uthread_swapcontext()切换到它(注意设置 UT_ON_CPU 线程状态和当前线程)。如果调用线程本身就是最高优先级线程,则切换回调用线程。主要工作:找出系统中优先级最高的线程,并切换(必须要有可执行线程)。

uthread_init:这个函数只在用户进程启动时调用一次,用于初始化所有的全局数据结构和变量。这个函数需要设置每一个线程的 ut_state 和 ut_id,简单起见,本系统中选择线程数组的下标作为 ut_id。
uthread_create:创建一个线程执行指定的函数,函数的参数为和,优先级为。首先,使用uthread_alloc找到一个有效的id,找不到时,返回合适的错误;然后,为线程分配栈,分配不成功时返回合适的错误;使用uthread_makecontext()创建线程的上下文;按照新发现的线程id,设置uthread_t结构,调用uthread_setprio设置线程的优先级,在中返回线程id。不成功时返回0。
uthread_exit:结束当前的线程(注意设置 uthread_t 中的标志)。如果线程是 UT_DETACHABLE,则通过调用 make_reapable()将其放入清理线程(reaper)清理队列并唤醒清理清理线程。如果线程是 UT_JOINABLE,则唤醒等待的线程。然后调用 uthread_switch()切换线程。

uthread_join:等待指定的线程结束,如果线程没有结束执行,调用线程需要阻塞,直到线程结束。主要工作:如果要等待的线程还没有结束,则置线程的等待线程为当前线程,线程状态改为 UT_WAIT,切换线程;如果成功地等到了线程结束,则调用 make_reapable 唤醒清理线程 reaper 将其彻底清理。错误条件及对应的 error code 参考 pthread_join 的 manpage。

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://download.csdn.net/download/sheziqiong/85821835
资源下载地址:https://download.csdn.net/download/sheziqiong/85821835
边栏推荐
- Advanced MySQL - storage engine
- Flutter技术与实战(1)
- Which version of JVM is the fastest?
- STM32按键消抖——入门状态机思维
- C语言微博用户管理系统
- What are the Commonwealth countries
- 为防止被00后整顿,一公司招聘要求员工不能起诉公司
- 分片信息调哪个参数呢?用的是MySQLsource stream api,不是table api
- About xampp unable to start MySQL database
- Real test = "half product + Half development"?
猜你喜欢

GNN notes: message propagation model

一个简单但是能上分的特征标准化方法

Cv5200 ad hoc network remote WiFi module, UAV wireless image transmission application, HD low delay scheme

Stable currency risk profile: are usdt and usdc safe?

我,大厂测试员,降薪50%去国企,后悔了...

解题元宇宙,网络游戏中的多元通信方案

curl: (56) Recv failure: Connection reset by peer

连续10年霸榜第一?程序员「最常用」的编程语言是它?

基于opencv进行双目相机的标定

MySQL foundation - transaction
随机推荐
AI and creativity
穩定幣風險狀况:USDT 和 USDC 安全嗎?
Fluent的msh格式网格学习
Which version of JVM is the fastest?
图文带你彻底弄懂MySQL事务原子性之UndoLog
把这份关于软件测试一系列笔记研究完,进大厂是个“加分项”...
After 3 years of testing experience, do you know the state transition method for use case design?
Sophon autocv: help AI industrial production and realize visual intelligent perception
[untitled]
A tour of grpc:02 - generate code from proto
分片信息调哪个参数呢?用的是MySQLsource stream api,不是table api
In order to prevent being rectified after 00, a company requires employees not to sue the company
Tool chain empowers hundreds of companies, horizon opens the "Matthew effect" of mass production of intelligent driving
Which parameter is the partition information adjusted? The MySQL source stream API is used, not the table API
MySQL基础——多表查询
535. TinyURL 的加密与解密 / 剑指 Offer II 103. 最少的硬币数目
美国芯片再遭重击,Intel或将被台积电击败而沦落至全球第三
curl: (56) Recv failure: Connection reset by peer
6.26cf simulation game d: black and white questions
Advanced MySQL - storage engine