【uTenux实验】信号量
信号量(semaphore)是一个用来指示可用的资源并将可用资源的数量以数值的形式表示出来的对象。当使用一组资源时,信号量用来实现互斥控制和同步。uTenux提供了信号量出来的API,可以很方便地使用信号量。
uTenux中,信号量包含一个资源计数(用来指示是否存在相应的资源以及资源的数量)和一个等待信号量的任务队列。
当一个任务返回m个资源时,信号量资源计数加m。当一个任务获得n个资源时,信号量资源计数减n。如果信号量资源的数量不够(进一步减少信号量计数可能使其值变成负数),则尝试获取资源的任务进入等待状态,直至下次有资源返回。等待信号量资源的任务被置入信号量队列。
1、创建信号量:IDsemid=tk_cre_sem(T_CSEM*pk_csem);
T_CSEM为信号量结构体,定义如下:
typedef struct t_csem {
VP exinf; /*扩展信息,OS不关心 */
ATR sematr; /* 信号量属性*/
INT isemcnt; /* 信号量初始计数 */
INT maxsem; /* 最大信号量数目 */
UB dsname[8]; /* Object name */
} T_CSEM;
信号量的属性可以用下面的表达式得到:
sematr:=(TA_TFIFO||TA_TPRI)|(TA_FIRST||TA_CNT)| [TA_DSNAME]
TA_TFIFO 任务按FIFO的顺序排队
TA_TPRI 任务按优先级顺序排队
TA_FIRST 队列中第一个任务最先获得资源
TA_CNT 请求越少的任务越先获得资源
TA_DSNAME 设定DS对象名
等待信号量的任务的排队顺序可以设置成TA_FIFO或TA_TPRI。TA_FIRST和TA_CNT设定了获取资源的先后顺序
2、tk_sig_sem用来释放信号量
提供一个释放信号量的数目即可。如果没有超过最大信号量计数,释放后,信号量技术增加这个数目。
3、tk_wai_sem用来申请信号量。
关于信号的量申请:
如果一次需要获得多个信号量,但是信号量又不够。比如我需要3个信号量,但剩余的信号量只有1个。那么用tk_wai_sem申请信号量时候,不会改变信号量计数,然后开始等待其他信号量。
实验验证:
1、创建三个任务:任务A、B、C。其中任务A需要三个信号量,任务B需要4个信号量。任务A的优先级大于任务B。任务C为最低优先级的空闲任务。
2、创建任务后,先启动任务B,任务B先申请4个信号量。然后启动任务A。
3、由于任务A的优先级高于任务B,任务B被中断,任务A开始执行。由于系统中没有可用信号量,任务A申请信号量失败 进入等待状态。
4、之后回到任务B,任务B释放四个信号量。此时,系统中有足够的信号量供任务A使用,任务A被唤醒。继续执行。
5、任务A执行一次之后进入休眠,任务B开始执行。任务B申请并获得4个信号量,完成LED反转。之后释放信号量进入休眠。
6、两个任务都进入等待状态,任务C开始执行。任务C是一个死循环。用于防止OS没有正在运行的任务而退出。
实验代码如下:
//本实验中,信号量代表开发板上的是个LED
//任务B需要4个信号量,控制LED同时亮灭
//任务A需要3个信号量,控制LED1、2、3同时亮灭 #include "SemSample.h"
#include <dev/ts_devdef.h> void SemSampleTaskA(W stacd,VP exinf);
void SemSampleTaskB(W stacd,VP exinf);
void SemSampleTaskC(W stacd,VP exinf);
void SemSamplePutCnt(void);
static ID TaskID_A;
static ID TaskID_B;
static ID TaskID_C;
static ID semid; ER SemSample(void)
{
ER ercd = E_OK;
T_CTSK ctsk;
T_CSEM csem; ctsk.exinf = NULL;
ctsk.task = SemSampleTaskA;
ctsk.tskatr = TA_HLNG | TA_RNG0;
ctsk.stksz = 512;
ctsk.bufptr = NULL;
ctsk.itskpri = 24;
TaskID_A = tk_cre_tsk(&ctsk);
if(TaskID_A< E_OK)
{
ercd = TaskID_A;
return ercd;
} ctsk.itskpri = 26;
ctsk.stksz = 256;
ctsk.task = SemSampleTaskB;
TaskID_B = tk_cre_tsk(&ctsk);
if(TaskID_B < E_OK)
{
ercd = TaskID_B;
return ercd;
} ctsk.itskpri = 28;
ctsk.stksz = 256;
ctsk.task = SemSampleTaskC;
TaskID_C = tk_cre_tsk(&ctsk);
if(TaskID_C < E_OK)
{
ercd = TaskID_C;
return ercd;
} //创建一个信号量
csem.exinf = NULL;
csem.isemcnt = 4;
csem.maxsem = 4;
csem.sematr = TA_TFIFO | TA_FIRST;
semid = tk_cre_sem(&csem);
if(semid < E_OK)
{
ercd = semid;
return ercd;
}
SemSamplePutCnt(); //启动任务B
tk_sta_tsk(TaskID_B,5); return TRUE;
} void SemSampleTaskA(W stacd,VP exinf)
{
ER ercd = E_OK;
T_RSEM rsem;
rsem = rsem;
while(1)
{
tm_putstring((UB*)"任务A开始申请3个信号量\n");
SemSamplePutCnt();
ercd = tk_wai_sem(semid,3,500); SemSamplePutCnt();
if(ercd == E_OK)
{
LEDTog(LED1);
LEDTog(LED2);
LEDTog(LED3);
} tm_putstring((UB*)"任务A开始释放3个信号量\n");
tk_sig_sem(semid,3);
SemSamplePutCnt(); tk_slp_tsk(500);
} } void SemSampleTaskB(W stacd,VP exinf)
{
ER ercd = E_OK;
T_RSEM rsem; ercd = tk_sta_tsk(TaskID_C,0); SemSamplePutCnt();
tk_wai_sem(semid,4,-1);
ercd = tk_sta_tsk(TaskID_A,0);
if(E_OK == ercd)
{
tm_putstring((UB*)"Start TaskA sucessfuly.\n");
}
else
{
tm_putstring((UB*)"TaskB Failed start Task A.\n");
}
tk_sig_sem(semid,4);
//任务循环
while(1)
{
//任务B需要4个信号量 SemSamplePutCnt();
tm_putstring((UB*)"任务B开始申请4个信号量\n"); if(tk_wai_sem(semid,4,-1) == E_OK)
{
tm_putstring((UB*)"任务B成功获得4个信号量\n");
SemSamplePutCnt();
LEDTog(LED1);
LEDTog(LED2);
LEDTog(LED3);
LEDTog(LED4);
if(tk_sig_sem(semid,4) == E_OK)
{
tm_putstring((UB*)"任务B成功释放4个信号量\n");
}
else
{
tm_putstring((UB*)"任务B释放信号量失败\n");
}
}
else
{
tm_putstring((UB*)"任务B获取信号量失败\n");
}
tk_slp_tsk(200);
} } //防止任务全部休眠导致OS退出的空闲任务
void SemSampleTaskC(W stacd,VP exinf)
{
B b;
while(1)
{
tm_putstring((UB*)"this is in Task C\n");
for(b = 0;b<200;b++);
}
} void SemSamplePutCnt(void)
{
B semcnt[10];
T_RSEM rsem; tm_putstring((UB*)"当前的可用信号量数为: ");
tk_ref_sem(semid, &rsem);
ltostr(rsem.semcnt,semcnt,10,10);
tm_putstring((UB*)semcnt);
tm_putstring((UB*)"\n");
}
实验时串口输出信息:
----------------------------------------------------
micro Tenux Version 1.6.00(build 0180)
Supported MCU is ST STM32F407VG
Copyright(c) 2008-2013 by Dalian uLoong Co.,Ltd.
----------------------------------------------------
当前的可用信号量数为: 4
当前的可用信号量数为: 4
任务A开始申请3个信号量
当前的可用信号量数为: 0
Start TaskA sucessfuly.
当前的可用信号量数为: 1
任务A开始释放3个信号量
当前的可用信号量数为: 4
当前的可用信号量数为: 4
任务B开始申请4个信号量
任务B成功获得4个信号量
当前的可用信号量数为: 0
任务B成功释放4个信号量
this is in Task C
当前的可用信号量数为: 4
任务B开始申请4个信号量
任务B成功获得4个信号量
当前的可用信号量数为: 0
任务B成功释放4个信号量
当前的可用信号量数为: 4
任务B开始申请4个信号量
任务B成功获得4个信号量
当前的可用信号量数为: 0
【uTenux实验】信号量的更多相关文章
- 【uTenux实验】事件标志
事件标志是一个用来实现同步的对象,由多个位组成,用作指示对应事件存在的标志.事件标志由用来指示对应事件存在的位模式(bitpattern)和一个等待事件标志的任务队列组成. uTenux提供了一组AP ...
- 【uTenux实验】写在开始实验之前
1.使用的uTenux内核代码:http://www.uloong.cc/cn/download/uTenux_V1.6.00r180.zip 2.uTenux的特性: 1.微内核 2.开放源码.完 ...
- 【uTenux实验】任务管理
任务就是一个无限循环.uTenux提供的任务管理功能是很强大的,包括建立和删除一个任务,启动或退出任务,取消一个任务的启动请求,改变任务的优先级和査询任务状态,使任务进人睡眠状态和唤醒状态,取消唤醒请 ...
- 【uTenux实验】邮箱
邮箱是一个通过在系统(共享)内存空间传递消息来实现同步和通信的对象.uTenux中每个邮箱都包含一个用来发送消息的消息队列和一个用于等待接收消息的任务队列,其使用邮箱功能的消息内容放置在发送方和接收方 ...
- 【uTenux实验】互斥体
互斥体,维基百科中交互斥锁.其定义是这样的:互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制 ...
- 【uTenux实验】消息缓冲区
uTenux的消息缓冲区是一个通过传递大小可变的消息来实现同步和通信的对象. 消息缓冲区由三部分组成:1.待发消息队列 2.等接收消息的任务队列 3.用来保存缓冲消息的空间. 和信号相比,消息队列 ...
- 【uTenux实验】集合点端口
这个是头一次接触的概念.比较不好理解.内核规范中的说明就要20页! 看了王总写的uTenux内核规范之后,有那么一点明白了但理解不深. 集合点端口就像每次工作前的收集情况会.首长下达收集情况指令,各个 ...
- 【uTenux实验】内存池管理(固定内存池和可变内存池)
1.固定内存池管理实验 内存管理是操作系统的一个基础功能.uTenux的内存池管理函数提供了基于软件的内存池管理和内存块分配管理.uTenux的内存池有固定大小的内存池和大小可变的内存池之分,它们被看 ...
- 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)
1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...
随机推荐
- meta name="viewport" content="width=device-width,initial-scale=1.0" 解释
<meta name="viewport" content="width=device-width,initial-scale=1.0"> c ...
- 初学DOM树解析xml文件
做了一次设计模式实验的题目: 某软件公司为新开发的智能手机控制与管理软件提供了一键备份功能,通过该功能可以将原本存储在手机中的通信录.短信.照片.歌曲等资料一次性全部拷贝到移动存储介质(例如MMC卡或 ...
- Rhel6-varnish配置文档
系统环境: rhel6 x86_64 iptables and selinux disabled 主机: 192.168.122.160:virnish apache server60.example ...
- 国际性公司的中国化BPM业务流程管理怎么落地?
康奈可集团于1938年在日本成立,总部位于东京,日本康奈可自2002年开始投资中国,现已在江苏无锡.湖北襄樊和广州地区投资设立8家公司,总投资超过1亿美元.公司主要生产汽车模块及散热器.车用空调.消音 ...
- golang——slice使用摘要
1.slice因capacity不足而重新分配的underlying array与原本的array空间是断裂的,就是说这是原本指向的空间没变,如下 arr := [...]int{1, 2, 3, 4 ...
- fragment切换刷新 及下拉刷新
此工程较BaiduLocationXMLFragmentDB相比:1.滑动fragment自动刷新该fragment2.下拉刷新fragment,上拉暂未实现 a.fragment切换刷新 1 . 由 ...
- C++中不同数据类型的互相转换
1.string --> char * char * p = (char*)str.c_str(); 2.char * -->string char *p = "aaa& ...
- iMacros 教程
imacros能记录你在网页中的动作,然后模拟你的动作自动重复执行.进阶应用主要在于两个方面: 1.用JS动态调用,重复执行之. 2.调用CSV文件,这个不错哦. 还可以调用数据库,这个没用过. 安装 ...
- WebService Ajax调用
1.Html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
- Warning: Attempt to dismiss from view controller <UIViewController: 0x17d71c10> while a presentation or dismiss is in progress!
昨天 调试程序 已经快要上线了 突然有个BUG 找了半天 才找到是因为这个警告 但是 解决这个警告又花了一天的时间 试了各种消除控制器的方法 都不可用 其中 并且 有这个bug 手机真机测试完全没问 ...