vxWorks操作系统提供了一套丰富的任务间通信机制,包括:共享内存、信号量、Mutexe、信号队列和管道、socket、信号
1. 共享内存
2.互斥
当共享内存进行数据交换时,为避免竞争,需要对内存进行互锁。
2.1 中断上锁
funcA()
{
int lock = inLock();
/* 禁止中断的代码临界区 */
intUnLock(lock);
}
注意:对实时系统一般不使用,因为上锁期间会阻止系统对外部事件的响应。一旦要求紧急响应外部事件时,中断时间将难以接受
2.2 抢占上锁
抢占上锁时,中断服务程序仍然能够执行
funcA()
{
taskLock();
/* 禁止中断的代码临界区 */
taskUnLock();
}
3. 信号量
vxWorks操作系统中,信号量提供最快的任务间通信机制。是任务互斥和同步的最主要手段。
分3中类型:
==二进制信号量:==最快最通用的信号量,适用于同步和互斥
==互斥信号量:==解决内在互斥问题,优先级继承问题
==计数信号量:==类似二进制信号量,解决单个资源多个实例需要保护的情况
3.1 信号量控制
调用函数 | 描述 |
---|---|
semBCreate | 分配并初始化一个二进制信号量 |
semMCreate | 分配并初始化一个二进制信号量 |
semCCreate | 分配并初始化一个计数器信号量 |
semDelete | 终止并释放一个信号量 |
semTake | 获取信号量 |
semGive | 提供信号量 |
semFlush | 解除正在等待信号量的任务 |
3.2 二进制信号量
可以满足两种任务的同步、互斥需要。信号量可用为full,调用taskTake()使其变为不可用,
#incldue "vxWorks.h"
#include "semLib.h"
SEM_ID semMutex;
/* 创建一个二进制信号量,该信号量最初为可用的 */
/* 阻塞在信号量上,按优先级顺序等待信号量 */
semMutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
/* 当需要访问某个资源时必须先获取信号量 */
semTake();
/* 临界资源 任何时间仅单个任务可以访问*/
semGive();
中断与信号量的结合,在中断处理函数中释放信号量。另一个一直阻塞获取信号量的任务得到信号量后执行。
SEM_ID producerSem; //定义一个二进制信号量ID
/*中断初始化 */
int timer_init()
{
int ret = 0;
sysAuxClkRateSet(100); //设置软定时器频率,tick/秒
sysAuxClkDisable(); //禁用软定时器
ret = sysAuxClkConnect((FUNCPTR)timer_callback, 0);//中断连接
sysAuxClkEnable(); //使能中断
return 0;
}
int timer_callback()
{
semGive(producerSem); //释放信号量
//TcpSendFlog = 1;
return 0;
}
int main()
{
producerSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY);//创建二进制信号量
timer_init();
while(1)
{
semTake(producerSem); //阻塞获取信号量
/* 定时中断到后,执行代码 */
}
return 0;
}
3.3 互斥信号量
基本行为同二进制信号量
不同之处:
它仅用于互斥
仅能由提取它(semTake)的任务释放,不能在中断服务程序中释放
/* 基于优先级继承创建的信号量 */
/* SEM_INVERSION_SAF选项可以继承优先级算法 */
/* 必须与优先级队列SEM_Q_PRIORITY 选项一同使用 */
semID = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
3.4 特定的信号量选项
semTake(NO_WAIT),表示系统不需要等待
semTake(WAIT_FOREVER),无限期等待
4. 消息队列
消息队列对允许数目可变、长度可变的消息进行排队。多个任务可以同事向一个消息队列中发送和接收消息。两个任务间的全双工通信一般需要两个消息队列,每个方向一个消息一个消息队列。
调用函数 | 描述 |
---|---|
msgQCreate() | 分配并初始化一个消息队列 |
msgQDelete() | 终止并释放一个消息队列 |
msgQSend() | 向消息队列发送消息 |
msgQReceive() | 从消息队列接收消息 |
5. 管道
管道使用vxWorks操作系统中的I/O系统,调用时需要指定管道创建名称、能排列的消息最大数目以及每个消息的最大长度。
status = pipeDevCreate("/pipe/name", max_msgs, max_length);
//可以使用标准IO函数对管道进行打开、读写,另外也可以调用ioctl
//满管道写数据和空管道读取数据将阻塞
//中断服务程序能够向管道写入,但不能从管道zhong读取