【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.分别用于 ...
随机推荐
- .htaccess根据IP地址限制访问
屏蔽IP地址 屏蔽IP地址有时是非常必要的,比如对于一个外贸公司网站,来自国内的访问是不会带来任何经济效益的,而且还占用服务器资源,造成访问延迟等问题. 如果要屏蔽某一特定IP可以使用: order ...
- 在 Ubuntu 14.04 中配置 PXE 服务器
PXE(预启动执行环境Preboot Execution Environment)服务器允许用户从网络中启动 Linux 发行版并且可以不需要 Linux ISO 镜像就能同时在数百台 PC 中安装. ...
- Android Studio插件推荐(PreIOC,GsonFormat)
好的插件能加快项目的开发速度,尤其是一些针对重复性的代码的插件,所以在这里向大家推荐2款不错的插件,如果以后发现新的好的插件,还会继续推荐,同时欢迎大家推荐 GsonFormat GsonFormat ...
- DAO JDBC 学生成绩管理系统
1:student.course类 package JDBCU; public class Student { private String no; private String name; publ ...
- qsort函数
qsort函数用法举例 #include <stdio.h> #include <stdlib.h> #include <string.h> //数字比较函数 in ...
- Spring Bean配置
Spring 是什么 •Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. •Spring 是一个 IOC(DI) 和 ...
- 用dbforge调试procedure
工具官网地址:http://www.devart.com/dbforge/mysql/studio/ 对于某些存储过程很多且复杂的SQL的应用,在短时间内要使得所有MySQL存储过程和函数正常运行,那 ...
- 烟草公司基于BPM的IT一体化变革
广州烟草有限公司隶属于广东省烟草专卖局,中国烟草总公司统一领导.垂直管理.主要职能是负责广州市的烟草生产.经营企业和市场的专卖管理.成立20多年来,广州烟草致力于烟叶和卷烟的生产经营.多元化经营.技术 ...
- 个推推送iOS版 常见问题详解
原文:http://www.oschina.net/question/1782938_234760 1.提交了.p12文件后多久可以测试? 提交后10分钟左右才可以测试,并不是立即生效的. 2 ...
- Python的平凡之路(9)
一.Paramiko模块练习 1. Paramiko模块介绍 Paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接 2 .SSHclie ...