任务间通信:信号量、消息队列

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

vxworks中任务间的通信支持信号量、消息队列、管道、信号、事件

一:信号量
信号量分二进制信号量、互斥信号量、计数信号量。
1:二进制信号量
(1)semBCreate():创建二进制信号量
SEM_ID semBCreate(int options,SEM_B_STATE initialState)
options 可以为基于优先级的队列EM_Q_PRIORITY(0x1)或者是基于先进先出的队列SEM_Q_FIFO(0X0).
initialState 可以是信号量初始化为满SEM_FULL(1)或者为空SEM_EMPTY(0)。

注明:
1、互斥中的信号量与任务优先级的关系:任务的调度还是按照任务优先级进行,但是在使用临界资源的时候只有一个任务获得信号量,
也就是说还是按照任务优先级获得信号量从而访问资源。只是当前使用资源的任务释放信号量semGive(),其它任务按照优先级获得信号量。
2、信号量属性中的参数为:SEM_Q_PRIORITY。而且在创建信号量的时候必须把信号量置为满SEM_FULL。即信号量可用。
基本实现互斥模型:
SEM_ID semMutex;
semMutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
task(void)
{
semTake(semMutex, WAIT_FOREVER);//得到信号量,即相当于得到使用资源的令牌
//临界区,某一个时刻只能由一个任务 访问
semGive(semMutex);
}
关于任务同步的实现
同步即任务按照一定的顺序先后执行,为了实现任务A和B同步,只需要让任务A和B共享一个信号量,并设置初始值为空,即不可用,
将semGive()置于任务A之后,而在任务B之前插入semTake()即可。
说明:1、还是讨论和优先级的关系。由于信号量初始化为空,不可用,所以可能使得优先级反转,即高优先级任务B在等待低优先级任务A释放信号量。
只有执行了信号量释放语句semGive()后任务B得到信号量才能执行。
2、属性参数的设置为SEM_Q_FIFO,SEM_EMPTY;
实现模型参考
SEM_ID semSync;
semSync = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
taskA(void)
{
......
semGive(semSync); //信号量释放,有效
}
taskB(void)
{
semTake(semSync, WAIT_FOREVER); //等待信号量
....
}

taskSpawn:创建并激活任务,有点类似于VC下的启动线程函数:
int taskSpawn
(
char *name, /*你要创建的任务名:比如说task1,在Shell下可以用命令:i 来查看当前系统中所有的任务*/
int priority, /*任务优先级,*/
int options, /*一般为0*/
int stackSize, /* 需要申请堆栈的大小*/
FUNCPTR entryPt, /*回调函数,*/
int arg1, /*传递给处理任务回调函数所需要的参数*/
int arg2,
int arg3,
int arg4,
int arg5,
int arg6,
int arg7,
int arg8,
int arg9,
int arg10
)
用法:
taskSpawn("CANR1", 230, 0, 1024*32, (FUNCPTR)RecvProc,cardNo,1,0,0,0,0,0,0,0,0);

(2)semTake(): 获取信号量
STATUS semTak

e(SEM_ID semID,int timeout)
semID为信号量ID。
timeout 表示任务一直等待信号量,直到可用WAIT_FOREVER(-1)或者不等待,直接下步操作NO_WAIT(0)。
(3)semGive():释放信号量
STATUS semGive(SEM_ID semID)
(4)semFlush():唤醒信号量
STATUS semFlush(SEM_ID semID)
通过此函数可以将所有阻塞在信号量(WAIT_FOREVER)上的任务释放。
(5)semDelete():删除信号量
STATUS semDelete(SEM_ID semID)
(6)semInfo():得到阻塞在信号量上的所有任务ID列表
int semInfo(SEM_ID semID,int idList[],int maxTasks)
idList[]为要显示任务ID的数组。
maxTasks为要显示的任务最大数。
(7)semShow():显示信号量的相关信息
STATUS semShow(SEM_ID semID,int level)
level分概括(0),详细(1)。


二:消息队列
Vxworks系统中提供了两种消息队列库:msgQLib和mqPxLib。
msgQLib提供了标准的vxworks消息队列,而msPxLib提供了POSIX消息队列。
(1)msgQCreate():创建或者初始化消息队列
MSG_Q_ID msgQCreate(int maxMsgs,int maxMsgLength,int options)
maxMsgs 为最大消息数
maxMsgLength 消息的最大字节数
options 信息的属性
其中options可以为
-MSG_Q_FIFO(0x00):任务以FIFO原则排队。 (先进先出原则)
-MSG_Q_PRIORITY(0X01):任务以基于优先级的原则排队。
-MSG_Q_EVENTSEND_ERR_NOTIFY(0X02):消息队列向他的注册任务发送事件失败时,将返回一个ERROR的值,并且正确地设置errno。成功创建消息队列后会返回消息队列ID。
(2)msgQDelete():删除消息队列
STATUS msgQDelete(MSG_Q_ID msgQId) //要删除的消息队列

vxworks中任务间的通信支持信号量、消息队列、管道、信号、事件、共享内存等。
一:信号量
信号量分二进制信号量、互斥信号量、计数信号量。
1:二进制信号量
(1)semBCreate():创建二进制信号量
SEM_ID semBCreate(int options,SEM_B_STATE initialState)
options 可以为基于优先级的队列EM_Q_PRIORITY(0x1)或者是基于先进先出的队列SEM_Q_FIFO(0X0).
initialState 可以是信号量初始化为满SEM_FULL(1)或者为空SEM_EMPTY(0)。
(2)semTake(): 获取信号量
STATUS semTake(SEM_ID semID,int timeout)
semID为信号量ID。
timeout 表示任务一直等待信号量,直到可用WAIT_FOREVER(-1)或者不等待,直接下步操作NO_WAIT(0)。
(3)semGive():释放信号量
STATUS semGive(SEM_ID semID)
(4)semFlush():唤醒信号量
STATUS semFlush(SEM_ID semID)
通过此函数可以将所有阻塞在信号量(WAIT_FOREVER)上的任务释放。
(5)semDelete():删除信号量
STATUS semDelete(SEM_ID semID)
(6)semInfo():得到阻塞在信号量上的所有任务ID列表
int semInfo(SEM_ID semID,int idList[],int maxTasks)
idList[]为要显示任务ID的数组。
maxTasks为要显示的任务最大数。
(7)semShow():显示信号量的相关信息
STATUS semShow(SEM_ID semID,int level)
level分概括(0),详细(1)。

2:互斥信号量
互斥信

号量相比二进制信号量增加了防止优先级倒置、递归访问等功能。
(1)semMCreate():创建互斥信号量
SEM_ID semMCreate(int options)
options 的选项有:
- SEM_Q_PRIORITY(0x1):需要获取信号量的任务基于优先级原则排列。
- SEM_Q_FIFO(0x0):需要获取信号量的任务基于先进先出原则排列。
- SEM_DELETE_SAFE(0x4):保护任务防止意外删除,当执行获取信号量(semtake)时操作时会默认执行任务保护

(taskSafe)操作,当执行释放信号量(semGive)操作时会默认执行取消任务保护(taskUnsafe)操作。
- SEM_INVERSION_SAFE(0x8):保护系统,防止系统出现优先级倒置现象。
- SEM_EVENTSEND_ERR_NOTIFY(0X10):任务发送事件失败时,会发送错误号。
(2)semMGiveForce():强制释放互斥信号量
STATUS semMGiveForce(SEM_ID semId)

3:计数信号量
计数信号量主要用于搜集某些信号量。
SEM_ID semCCreate(int options,int initialCount)
options为信号量属性或类型
initialCount 初始化计数
/************************************************************************
示例代码:以二进制信号量为例
STATUS task1(void); //声明两个任务
STATUS task2(void);
int taskId1,taskId2; //全局变量任务ID
SEM_ID semTest1,semTest2; //信号量
int initTask() //任务初始化
{
taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1
taskId2=taskSpawn("task2",120,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2
semTest1=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); //创建信号量1
semTest2=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); //创建信号量2
if(semTest1==NULL) //如果创建信号量失败,则返回错误,成功着返回OK
{
return ERROR;
}
return OK;
}

STATUS task1(void) //任务1主体函数
{
while(1)
{
semGive(semTset1); //任务1释放信号量1
printf("任务1释放了信号量!\n");
semTake(semTest2,WAIT_FOREVER);//任务1得到信号量2,在任务2没有释放信号量2前,任务1在此等待
printf("任务1得到了信号量!\n");
}
}

STATUS task1(void)//任务2主体函数
{
while(1)
{
semTake(semTest1,WAIT_FOREVER);//任务2得到信号量1,在任务1没有释放信号量1前,任务2在此等待
printf("任务2得到了信号量!\n");
semGive(semTset2); //任务2释放信号量2
printf("任务2释放了信号量!\n");
}
}
********************************************************************************/

二:消息队列
Vxworks系统中提供了两种消息队列库:msgQLib和mqPxLib。
msgQLib提供了标准的vxworks消息队列,而msPxLib提供了POSIX消息队列。
(1)msgQCreate():创建或者初始化消息队列
MSG_Q_ID msgQCreate(int maxMsgs,int maxMsgLength,int options)
maxMsgs 为最大消息数
maxMsgLength 消息的最大字节数
options 信息的属性
其中options可以为
-MSG_Q_FIFO(0x00):任务以FIFO原则排队。

-MSG_Q_PRIORITY(0X01):任务以基于优先级的原则排队。
-MSG_Q_EVENTSEND_ERR_NOTIFY(0X02):消息队列向他的注册任务发送事件失败时,将返回一个ERROR的值,并且正确地设置errno。成功创建消息队列后会返回消息队列ID。
(2)msgQDelete():删除消息队列
STATUS msgQDelete(MSG_Q_ID msgQId) //要删除的消息队列
(3)msgQSend():发送消息队列
STATUS msgQSend(MSG_Q_ID msgQId, //要发送的消息队列
char* buffer, //要发送的消息指针
UINT nBytes, //消息长度
int timeout, //等待的tick数 当为NO_WAIT(0)时,
表示消息没有发送出去也立刻返回,当为WAIT_FOREVER(-1)时,则一直等待发送,直到消息发送出去
int priority //普通(MSG_PRI_NORMAL(0))还是紧急模式(MSG_Q_PRI_URGENT(1))
)
(4)msgQReceive():从消息队列中收取消息
int msgQReceive(MSG_Q_ID msgQId, //接收的消息队列ID
char* buffer, //接收消息的BUFFER指针,
如果消息超过了BUFFER的最大字节数,则超出的部分将被丢弃。
UINT maxNBytes, //BUFFER的最大字节数
int timeout //等待的tick数,当为NO_WAIT(0)时,
表示消息没有发送出去也立刻返回,当为WAIT_FOREVER(-1)时,则一直等待收取,直到消息收取到
)
(5)msgQNumMSgs():得到排队到消息队列中的消息数
int msgQNumMsgs(int MSG_Q_ID msgQId) //消息队列的ID
该函数返回排队到消息队列中的消息数。



相关文档
最新文档