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

    技术2022-05-13  2

    2010/11/14 21:47

    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; //全局变量任务IDSEM_ID semTest1,semTest2; //信号量int initTask()   //任务初始化{taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1taskId2=taskSpawn("task2",120,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2semTest1=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); //创建信号量1semTest2=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); //创建信号量2if(semTest1==NULL)   //如果创建信号量失败,则返回错误,成功着返回OK{   return ERROR;}return OK;}

    STATUS task1(void) //任务1主体函数{while(1){semGive(semTset1);             //任务1释放信号量1printf("任务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释放信号量2printf("任务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该函数返回排队到消息队列中的消息数。/**********************************************************************************示例代码:STATUS task1(void); //声明两个任务STATUS task2(void);

    int taskId1,taskId2; //全局变量任务IDMSG_Q_ID msgQId1; //消息队列IDchar buffer[50]; //接收消息的buffer

    int initTask()   //任务初始化{taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1taskId2=taskSpawn("task2",120,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2msgQId=msgQCreate(20,50,MSG_Q_PRIORITY); //创建消息队列if(msgQId==NULL)   //如果创建信号量失败,则返回错误,成功着返回OK{   return ERROR;}return OK;}

    STATUS task1(void) //任务1主体函数{while(1){if(msgQSend(msgQId1,MSG,sizeof(MSG),WAIT_FOREVER,MSG_PRI_NORMAL)==ERROR)//向消息队列发送消息MSG{    return ERROR;}taskDelay(10);}}

    STATUS task1(void)//任务2主体函数{while(1){if(msgQReceive(msgQId1,buffer,50,WAIT_FOREVER)==ERROR)//从消息队列接收消息{    return ERROR;}printf("消息是%s/n",buffer);//将消息的内容显示出来}}*********************************************************************************/

    三:管道管道是一种虚拟的I/O设备,所以对管道可以通过标准的I/O口函数进行操作。(1)pipeDevCreate():创建管道STATUS pipeDevCreate(char* name,int nMessages,int nBytes)name 为管道名nMessages 为管道中的最大数目nBytes 为每个消息的字节数(2)pipeDevDelete():删除管道STATUS pipeDevDelete(char* name,BOOL force)force 为是否要强制删除(3)pipeDrv():初始化管道STATUS pipeDrv(void)/*********************************************************************************示例代码:管道#define MSG "hello"

    STATUS task1(void); //声明两个任务STATUS task2(void);

    int taskId1,taskId2; //全局变量任务IDint pipeId;int temp;char buffer[50];

    int initTask()   //任务初始化{taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1taskId2=taskSpawn("task2",120,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2temp=pipeDevCreate("/pipe/pipeTest",50,50); //创建管道if(temp==ERROR){return ERROR;}pipeId=open("/pipe/pipeTest",O_RDWR,0); //打开管道if(pipeId==ERROR){return ERROR;} return OK;}

    STATUS task1(void) //任务1主体函数{while(1){if(write(pipeId,MSG,sizeof(MSG))==ERROR)//向管道写信息{    return ERROR;}taskDelay(10);}}

    STATUS task2(void)//任务2主体函数{while(1){if(read(pipeId,buffer,50)//向管道里读信息{    return ERROR;}printf("消息是%s/n",buffer);//将消息的内容显示出来}}*************************************************************************/

    四:信号信号是由事件引发的软中断,中断并非由外界硬件产生,而是由内部程序自己产生。需要特别注意的是,信号的处理程序并非在中断上下文中进行处理,而是在接受任务本身的上下文中进行处理。(1)signal():将信号与特定的处理程序绑定void (*signal(int signo,void(*pHandler)()))signo 为信号ID,*pHandler () 为信号处理程序(2)kill():向指定的任务发送信号int kill(int tid,int signo)tid 为任务IDsigno 为要发送的信号/**************************************************************************************示例代码:信号#define MSG "hello"

    STATUS task1(void); //声明两个任务STATUS task2(void);

    int taskId1,taskId2; //全局变量任务IDint signalTest=5;

    int initTask()   //任务初始化{taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1taskId2=taskSpawn("task2",120,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2return 0;}

    STATUS task1(void) //任务1主体函数{signal(signalTest,sigISR); //将信号与信号处理程序绑定while(1){}}

    void sigISR(int sig)//任务2主体函数{

    if(sig==signalTest){   logMsg("信号数是%d/n",sig,0,0,0,0,0); //输出信息}return;}

    STATUS task2(void) //任务1主体函数{while(1){kill(taskId1,signalTest);//发送信号给任务1taskDelay(10);}}******************************************************************************************/

    五:事件事件用于任务之间或者任务与ISR,或者任务与系统之间。任务最多可以注册24个事件,每个任务的TCB中有专门的事件寄存器,但此寄存器不可直接访问,有事件发生变化的时候会改变相应的寄存器值。(1)eventReceive():接收事件STATUS eventReceive(UINT32 events,UINT8 options,int timeout,UINT32* pEventsReceived)events 为等待的事件号timeout 为等待的事件pEventsReceived 为反映接收到的事件变量其中options可选项为:-EVENTS_WAIT_ANY(0X1):等待任何一个事件发生了就就绪-EVENTS_WAIT_ALL(0X0):等待所有事件发生了再就绪-EVENTS_RETURN_ALL(0X2):返回所有等待的和不等待的事件-EVENTS_FETCH(0X80):pEventsReceived变量设置已经接收到的事件相应位,并且立刻返回。(2)evenSend():发送事件STATUS eventSend(int taskId,UINT32 events)taskId 为要发送的任务events 为要发送的事件(3)evenClear():清除当前任务的所有事件(4)semGive():将事件拷贝到在该信号量注册的事件寄存器(5)msgQSend():将事件拷贝到在该队列注册的事件寄存器/**********************************************************************************************示例代码:事件

    STATUS task1(void); //声明两个任务STATUS task2(void);

    int taskId1,taskId2; //全局变量任务IDSEM_ID semId1; //促使事件发生的资源

    int initTask()   //任务初始化{taskId1=taskSpawn("task1",120,0,10240,(FUNCPTR)task1,0,0,0,0,0,0,0,0,0); //创建任务1taskId2=taskSpawn("task2",110,0,10240,(FUNCPTR)task2,0,0,0,0,0,0,0,0,0); //创建任务2semId1=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY); //创建二进制信号量if(semId1==NULL){return ERROR;}return OK;}

    STATUS task1(void) //任务1主体函数{UINT32 tmp_receive;semEvStart(semId1,VXEV01,EVENTS_OPTIIONS_NONE);//任务1在资源:二进制信号量semId1上注册,如果资源发生变化,则任务会收到相应的事件while(1){eventReceive(VXEV01,WAIT_ANY,WAIT_FOREVER,&tmp_receive);//等待事件发生if((tmp_receive&VXEV01)!=0){    printf("收到事件!/n");}}}

    STATUS task2(void)//任务2主体函数使信号量的可用状态发生变化,促使事件发生{while(1){semGive(semId1);semTake(semId1,NO_WAIT);taskDelay(10);}}


    最新回复(0)