📄 semtest.c
字号:
/*
该实验是Vxworks任务通信的信号量通信实验。
实验模拟了一个数据采集系统,在这个系统中:
progStart()、progStop()分别用来启动、停止本演示程序。它们分别给出了信号量的创建与删除的方法。
tCosmos任务被用来仿真接受中断的服务程序。它们分别给出了信号量的创建与删除的方法。
数据分成两个阶段处理:首先收集SUM_SAMPLE个数据,组成一个样本;然后对样本进行处理。两个阶段分别由任务tSchlep与任务tCrunch来完成,两者通过信号量来同步。
数据处理的结果由tMonitor来显示。
通过progStart()来启动实例程序。启动过程中,先创建信号量,在创建任务,以保证信号量在被任务使用之前已经创建。
Cosmos()仿真了数据接受中断的服务程序。Cosmos自动产生数据,然后利用二进制信号dataSemld的同步功能,释放信号量通知数据处理任务tSchlrp处理产生的数据。
nodeAdd()用于将样本数据储存到数据链表。由于数据链表为临界资源,所以在访问时使用了互斥信号量进行保护。本实例中的任务通过调用nodeAdd()来统一执行向数据链表中的插值操作。
Schlep()用于将采集到的数据组成一个样本。它通过二进制信号量dataSemld来等待采集的数据,然后调用nodeAdd()来互斥的保存样本数据,最后利用二进制着了syncSemld的同步功能,唤醒等待的任务tCrunch。
nodeScrap()用于从数据链表中删除首个数据节点。由于数据链表为互斥资源,所以在访问时使用了互斥信号量进行保护。本实例中的任务通过调用nodeScrap()来统一执行从数据链表删除节点的操作。
Crunch()用于处理样本数据。Crunch()首先利用二进制信号量的同步功能,等待tSchlrp发送一个样本;然后利用互斥信号量互斥的访问样本,并利用互斥信号量的递归访问功能,调用nodeScrap()来删除数据;最后将样本数据之和保存到result中,供tMonitor使用。
*/
#include "vxWorks.h"
#include "stdio.h"
#include "stdlib.h"
#include "semLib.h"
#include "taskLib.h"
/*样本数据个数*/
#define NUM_SAMPLE 10
/*模拟产生数据的间隔事件*/
#define DELAY_TICKS 8
/*分配给每个任务的堆栈大小*/
#define STACK_SIZE 20000
/*数据类型定义*/
typedef struct _LIST_NODE
{
int data;
struct _LIST_NODE *pNextNode; /*指向下一个节点*/
}LIST_NODE;
/*任务ID定义*/
int tidCosmos;
int tidSchlep;
int tidCrunch;
int tidMonitor;
/*模拟产生的数据*/
int cosmicData = 0;
/*样本数据处理结果*/
int result = 0;
/*数据列表头指针*/
LIST_NODE* pCurrNode = NULL;
/*信号量ID定义*/
SEM_ID dataSemId;
SEM_ID syncSemID;
SEM_ID nodeListGuardSemId;
/*函数定义*/
void cosmos(void);
void nodeAdd(int data);
void schlep(void);
void crunch(void);
void monitor(void);
void progStop(void);
void nodeScrap(void);
STATUS progStart(void)
{
/*创建信号量*/
syncSemID = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
dataSemId = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
nodeListGuardSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
pCurrNode = NULL;
/*创建任务*/
tidCosmos = taskSpawn("tCosmos", 200, 0, STACK_SIZE, (FUNCPTR)cosmos, 0,0,0,0,0,0,0,0,0,0 );
tidSchlep = taskSpawn("tSchlep", 220, 0, STACK_SIZE, (FUNCPTR)schlep, 0,0,0,0,0,0,0,0,0,0 );
tidCrunch = taskSpawn("tCrunch", 240, 0, STACK_SIZE, (FUNCPTR)crunch, 0,0,0,0,0,0,0,0,0,0 );
tidMonitor = taskSpawn("tMonitior", 250, 0, STACK_SIZE, (FUNCPTR)monitor, 0,0,0,0,0,0,0,0,0,0 );
return OK;
}
void cosmos(void)
{
FOREVER
{
/*产生随机数据*/
cosmicData = rand();
/*释放信号量,由于初始化该信号量为空,此处作用是通知数据接受任务*/
semGive(dataSemId);
/*任务延迟,保证*/
taskDelay(DELAY_TICKS);
}
return;
}
void nodeAdd(int data)
{
/*创建新的数据节点*/
LIST_NODE *node;
if ((node = (LIST_NODE*)malloc(sizeof(LIST_NODE))) != NULL)
{
node->data = data;
/*访问数据链表*/
semTake(nodeListGuardSemId, WAIT_FOREVER);
node->pNextNode = pCurrNode;
pCurrNode = node;
semGive(nodeListGuardSemId);
}
else
{
printf("nodeAd: out of Memory. \ n");
taskSuspend(0);
}
return;
}
void schlep(void)
{
int i;
FOREVER
{
/*采集数据*/
for (i = 0; i < NUM_SAMPLE; i++)
{
semTake(dataSemId, WAIT_FOREVER);
nodeAdd(cosmicData);
}
/*发送样本给tCrunch*/
semGive(syncSemID);
}
return;
}
void nodeScrap(void)
{
/*指向首个数据节点*/
LIST_NODE *pTmpNode;
/*互斥访问数据链表*/
semTake(nodeListGuardSemId, WAIT_FOREVER);
if (pCurrNode != NULL)
{
pTmpNode = pCurrNode;
pCurrNode = pCurrNode->pNextNode;
free(pTmpNode);
}
semGive(nodeListGuardSemId);
return;
}
void crunch(void)
{
/*保存样本数据之和*/
int sampleSum;
FOREVER
{
/*数据清0*/
sampleSum = 0;
/*同步,等待样本*/
semTake(syncSemID,WAIT_FOREVER);
/*互斥访问数据链表*/
semTake(nodeListGuardSemId,WAIT_FOREVER);
while (pCurrNode != NULL)
{
sampleSum += pCurrNode->data;
/*递归访问,删除数据*/
nodeScrap();
}
semGive(nodeListGuardSemId);
/*更新结果*/
result = sampleSum;
}
result;
}
void monitor(void)
{
BOOL isHot = FALSE;
BOOL average = 0;
average = RAND_MAX * NUM_SAMPLE /2;
FOREVER
{
/*循环测试result和average值的大小,如果测试条件成功,输出*/
if ((!isHot) && (result >= average))
{
isHot = TRUE;
printf("Hot \n");
}
else
if (isHot && (result < average))
{
isHot = FALSE;
printf("COOL \n");
}
}
return;
}
void progStop(void)
{
result = semTake(nodeListGuardSemId, WAIT_FOREVER);
if (result == OK)
{
/*删除任务*/
taskDelete(tidCosmos);
taskDelete(tidSchlep);
taskDelete(tidCrunch);
taskDelete(tidMonitor);
/*清空数据链表*/
while (pCurrNode != NULL)
{
nodeScrap();
}
}
/*释放信号量*/
semDelete(dataSemId);
semDelete(syncSemID);
semDelete(nodeListGuardSemId);
printf("BYE\n");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -