原创 设计自己的嵌入式操作系统内核之八 ----- 互斥体实现

2011-8-1 19:39 3481 6 7 分类: MCU/ 嵌入式

1、概述
互斥体用于控制嵌入式操作系统中多个任务对共享资源的访问。这类资源在任意时刻最多容许一个任务访问。前面提到的信号量机制也能够实现这种功能。但互斥体相比信号量还提供了优先级反转问题的解决方法。

优先级反转问题,简而言之就是低优先级的任务占有了高优先级任务需要的资源,导致高优先级的任务阻塞。这样优先级高的任务反而不能得到执行,而执行的是低优先级任务。一般提到的解决方案有两种:优先级继承协议、天花板优先级协议。前者指当有高优先级的任务申请资源时,当前占有资源的低优先级任务被抬升到高优先级任务相同的优先级。后者,则是设定了等于或大于所有申请资源的任务的优先级。当高优先级任务申请资源时,当前占有资源的低优先级任务的优先级被抬升到设定的最高优先级。

eos中使用的天花板优先级协议。并且支持任务多次申请同一互斥体。

2、互斥体的实现

1)、互斥体结构
互斥体的结构示意图如下:

点击看大图

互斥体的结构定义如下:
typedef struct _mutex_t /* 互斥体结构 */
{
? uint8 ceil_prio; /* 互斥体拥有的优先级*/
? uint8 ref; /* 互斥体引用次数 */
? task_t owner; /* 互斥体占有者 */
? uint8 owner_prio; /* 互斥体占有者优先级*/
? mlist_t wait_list; /* 互斥体阻塞队列 */
? uint8 cflag; /* 互斥体控制标志 */
}* mutex_t;
其中.owner, owner_prio分别保存互斥体占有任务的指针和优先级。
.wait_list为阻塞队列。当互斥体已被占有时,其它申请互斥体的任务将进入该队列
.ref 为互斥体被当前任务占有的次数。eos允许互斥体被占有者多次申请占有。
.ceil_prio保存天花板优先级协议中指定的最高优先级。

另外,提供mqueue_info_t结构用于查询互斥体信息。结构如下:
typedef struct _mutex_info_t /* 互斥体消息结构 */
{
? uint8 ceil_prio; /* 互斥体拥有的优先级 */
? uint8 ref; /* 互斥体引用次数 */
? task_t owner; /* 互斥体占有者 */
? uint8 owner_prio; /* 互斥体占有者优先级 */
? uint8 cflag; /* 互斥体控制标志 */
}mutex_info_t;

2)、互斥体的接口函数:
主要包含互斥体的创建、销毁、申请、释放、查询操作。列表如下:
uint8 mutex_create( mutex_t * mutex, uint8 prio ); /* 创建一个互斥体 */
uint8 mutex_destroy( mutex_t mutex ); /* 销毁一个互斥体 */
uint8 mutex_request( mutex_t mutex, uint16 time_out ); /* 等待互斥体 */
uint8 mutex_try_request( mutex_t mutex ); /* 非阻塞等待互斥体 */
uint8 mutex_release( mutex_t mutex ); /* 释放互斥体 */
uint8 mutex_info( mutex_t mutex, mutex_info_t * info ); /* 查询互信息 */

各函数的操作流程如下:
mutex_create()操作流程:
参数检查
调用mpool_get()分配互斥体控制块结构struct _mutex_t
分配成功
是,
初始化控制块结构内部各域
初始化阻塞队列


mutex_info()操作流程:
参数检查
复制互斥体控制块信息至mutex_info_t结构中


mutex_destroy()操作流程:
参数检查
互斥体控制块.ref > 0,即互斥体已被占用
是,
检查cflag标志,是否已使能了优先级的调整

任务是否在处于多级队列中
是,
将任务从多级队列中移除
恢复原来的任务优先级
再将任务插入多级队列
否,?
恢复原来的优先级

销毁互斥体的是否为当前任务
是,
修改OSPrioCur为任务原来的优先级

调用event_mlist_del()销毁互斥体的阻塞队列
调用scheduler()进行调度

调用mpool_free()回收互斥体控制块
注:如果有互斥体已经做了优先级的调整,则当销毁互斥体时有必要恢复占有者任务的优先级。优先级的恢复不只是修改任务的task_struct结构。如果任务处于多级队列,还有必要将任务从当前处于的单级队列中移除,并移至原有优先级对应的单级队列。由于前面的设计中,即便使处于运行态的任务也处于就绪队列中,因而此时不并需要判定占有的任务是否处于多级队列中,可作统一的处理。对于当前处于单级队列,如只使用单级阻塞队列的信量,只需修改任务的优先级值即可。

mutex_request()操作流程:
参数检查
是否在中断中或调度器上锁时调用
是,立即返回

检查控制块域.ref,是否互斥体已被占有
否,
如果当前任务优先级比互斥体的.ceil-prio值更小,
不合法优先级,退出

锁定当前互斥体,域 . ref++
返回

是,已被占用
占有者是否为当前任务
是,
控制块域.ref++, 退出
否,
申请者优先级是否比占有者的更高
是,
是否已经进行了优先级调整
否,
任务是否处于多级队列
是,
将任务从现有多级队列移除
修改任务优先级为设定的互斥体优先级
再将任务插入多级队列
否,
修改当前任务优先级

调用event_mlist_wait()将当前任务插入互斥体阻塞队列
调用scheduler()切换至其它任务

返回OSTaskCur->wait_state域
返回OS_ERR_OK

注:容许已占有互斥体的任务多次申请占有互斥体。

mqueue_try_request()操作流程:
参数检查
检查控制块域.ref,是否互斥体已被占有
否,
如果当前任务优先级比互斥体的.ceil-prio值更小,
不合法优先级,退出

锁定当前互斥体,域 . ref++
返回

是,已被占用
占有者是否为当前任务
是,
控制块域.ref++, 退出
mutex_release()操作流程:
参数检查
互斥体是否已被占用
否,
立即返回
是,
是否是占有者释放互斥体
否,
释放不合法,返回

是,
控制块.ref减1
.ref值是否为0
是,
检查cflag标志,是否已使能了优先级的调整
是,
将任务从就绪队列中移除
恢复原来的任务优先级
再将任务插入就绪队列

设定互斥体为阻塞队列中最高优先级的任务占有
调用event_mlist_rdy()唤醒阻塞队列最高优先级任务
调用scheduler()进行调度

注:由于互斥体只能被占有者释放,因而在对已使能优先级调整的互斥体进行优先级恢复时,要恢复的优先级的任务必是当前运行的任务,而且任务必处于就绪队列中。这样,对任务所在队列的修改直接变成将任务从就绪队列中某单级队列移至另一单级队列。

3、简单的演示
提供了一个简单的测试实例 app_mutex.c 演示了互斥体的操作。

4、问题与思考


五、相关源码
core.c / core.h ---------- 内核支持函数文件
mutex.c/ipc.h ----------- 互斥体实现文件

pdf





文章评论1条评论)

登录后参与讨论

用户245924 2010-6-5 20:27

我需要这全套资料 请问能否发到我的邮箱 miaojunfei0602@126.com 急用!!!!非常感谢

tengjingshu_112148725 2009-8-18 21:29

没想到又见你出山了:)

用户1362017 2009-7-27 19:59

参考 HS1101设计答辩 在本博客日志里头有。

用户526022 2009-7-27 18:59

你好,,我非常需要你的全套资料,,可以发给我吗??315998713@qq.com,,,非常感谢!!!!
相关推荐阅读
用户403611 2014-01-20 07:28
与TKScope仿真器同行(1) - 看门狗会让你无法调试
  前几日,中矿龙科的李工向我反映了一个有意思的问题: 在使用TKScope仿真器(型号AK100pro)调试STM32时,出现了一个非常奇怪的现像。在Keil环境中的源代码设置了一...
用户403611 2013-02-27 13:41
ARM指令仿真项目经历纪录一
这两天接了个新项目-ARM指令仿真项目,开发时间预期在两个月左右。这次将继承沿续自己以前做Cortex-A8、A9内核仿真项目时的方法,用日志纪录在开发过程中的各种问题解决方案和体会。限于某些原因...
用户403611 2013-02-27 13:39
电子工程师应尝试产品经理的角色
做技术两三年了,发现自己一直陷入到技术细节当中,而从来没有尝试跳出来去从整个产品的角度进行观察。这其中可能是因为需要了解的技术细节太多,没有闲暇去关注技术之外的东西。另一方面也与个人的视野不够开阔...
用户403611 2011-11-13 20:05
EDNChina的博客已经改得面目全面了
 之前有些日子没去ENDChina了。从08年起,断断续续地在这上面写一些技术类的Blog,到现在已经有快4年,虽然文章写的不多,但挺有感情的。   这两天回去看看,访问http://blog...
用户403611 2011-10-14 22:02
TKScope仿真器使用入门视频教程
  相对来说,看视频肯定要比看PDF文档要容易的多吧。部门之前仅在网上发布了TKScope仿真器使用的PDF文档。虽然文档写的很详细,但实际真正愿意去看的不多。前些日子自己录制了TKScope仿真AR...
用户403611 2011-09-18 23:00
尝试建立一个部门内部的知识库站点
前些天有事直接去找了下戚工反映TKScope仿真器方面的几个问题。问题解决之后闲聊了几句,其中就提及了建立一个共享的内部网络站点。当时我听了很兴奋,因为这个想法与我的不谋而合。早在刚进入这个部门不久,...
我要评论
1
6
关闭 站长推荐上一条 /3 下一条