3. 实验二 (信号量) 【回到开发进程列表】
1. 概念学习
作用
多任务系统中的各个任务在共享各类资源时,因为有些资源一次只能被一个任务使用, 为防止同时运行的多个任务出现资源争执的需要, 系统提供了资源排他机制 - 信号量。
先定义信号量关联的资源数,对资源进行使用的任务先进行资源查询,如果能够从信号量中获得资源,任务将继续处理,在不需要使用资源时,便释放资源。
如果不能从信号量中获得到所要的资源,任务便不能继续执行,迁移到 wait 状态,并进入信号量的等待队列中,处于等待的过程中的任务,如果可以得到资源,任务便从等待状态中脱出,迁移ready 状态。
属性
一个计数信号量:是一个 32 位的变量,初始值表示可以使用的资源数量,初始值为 0 表示资源开始处于锁住状态,一个非 0 的值表示有多个资源供多个任务访问。
等待信号量的 Task 的等待队列。等待队列属性可以是 FIFO 或者Priority 方式
相关函数
创建信号量: ID semid = tk_cre_sem ( T_CSEM *pk_csem )
释放信号量: ER ercd = tk_sig_sem ( ID semid, INT cnt )
等待信号量: ER ercd = tk_wai_sem ( ID semid, INT cnt, TMO tmout )
删除信号量: ER ercd = tk_del_sem ( ID semid )
查询信号量:ER ercd = tk_ref_sem ( ID semid, T_RSEM *pk_rsem )
2. 实验操作
在实验的例程中创建了三个任务:初始化任务、任务A和任务B,其优先级顺序为A->B->初始化任务;
在初始化任务中分别创建了任务A,B以及一个信号量,且信号量初始化资源数为10;
在完成任务A,B及信号量的创建后优先启动了B任务,然后在B任务中必须先启动A任务;
在A任务的启动过程中需要等待一刚刚创建的信号量10个资源当中的一个资源,而此时10个资源都未被其他任务使用,所以A任务启动成功;
A任务启动成功后使会释放信号量,而且之后任务B启动也需要等待该任务量,如上面一样信号量资源充足,任务B启动成功,然后释放信号量,显示信号量资源数,唤醒任务A,未得到命令则循环这一步;
之后便是在任务B退出过程中删除信号量,任务A以及删除自身,关闭系统;
以上便是整个工作流程。
任务A代码
void SemSampleTaskA(W stacd,VP exinf)
{
ER ercd;
tm_putstring((UB*)"Task A is starting;\n"); // 指示任务A启动
// 进入任务A循环
for(;;){
tm_putstring((UB*)"Task A is waiting semaphore;\n"); // 等待信号量
ercd = tk_wai_sem(semid, 1, -1); // 等待一个资源,直到该资源可用为止
SemSamplePutCnt();
if (E_OK == ercd){
tm_putstring((UB*)"Task A get semaphore successfully;\n");
}else{
tm_putstring((UB*)"Task A can't get semaphore;\n");
PutErcd(ercd); // 显示错误代码
}
tm_putstring((UB*)"Task A release semaphore;\n");
ercd = tk_sig_sem(semid, 1); // 释放信号量,释放一个资源数
SemSamplePutCnt();
if (E_OK == ercd){
tm_putstring((UB*)"Task A release semaphore successfully;\n");
} else {
tm_putstring((UB*)"Task A can't release semaphore;\n");
}
tm_putstring((UB*)"Task A enter sleep status;\n");
tk_slp_tsk(-1);
}
}
任务B代码
void SemSampleTaskB(W stacd,VP exinf)
{
ER ercd;
B c;
ercd = tk_sta_tsk(TaskID_A,0);
if (E_OK == ercd){
tm_putstring((UB*)"Task B start Task A successfully;\n");
} else {
tm_putstring((UB*)"Task B can't start Task A;\n");
}
for(;;){
tm_putstring((UB*)"Task B is waiting semaphore;\n");
ercd = tk_wai_sem(semid, 1, -1);
SemSamplePutCnt();
if (E_OK == ercd){
tm_putstring((UB*)"Task B get semaphore successfully;\n");
} else {
tm_putstring((UB*)"Task B can't get semaphore;\n");
PutErcd(ercd);
}
tm_putstring((UB*)"Input Command(e=exit):\n");
c = tm_getchar(0);
if('e' == c) {
tm_putstring((UB*)"Exit from all task;\n");
break;
} else {
tm_putstring((UB*)"Task B release semaphore;\n");
ercd = tk_sig_sem(semid, 1);
SemSamplePutCnt();
if (E_OK == ercd){
tm_putstring((UB*)"Task B release semaphore successfully;\n");
} else {
tm_putstring((UB*)"Task B can't release semaphore;\n");
}
tm_putstring((UB*)"Task B wake up Task A;\n");
tk_wup_tsk(TaskID_A);
}
}
tm_putstring((UB*)"Task B delete semaphore;\n");
ercd = tk_del_sem(semid);
if (ercd == E_OK){
tm_putstring((UB*)"Task B delete semaphore successfully;\n");
} else {
tm_putstring((UB*)"Task B can't delete semaphore;\n");
}
tm_putstring((UB*)"Task B will terminate&delete task A;\n");
tk_ter_tsk(TaskID_A);
tk_del_tsk(TaskID_A);
tm_putstring((UB*)"Task B will terminate&delete self;\n");
tk_exd_tsk();
}