Vxworks信号量详解

来源:互联网 发布:myeclipse配置数据库 编辑:程序博客网 时间:2024/05/17 23:51


任务异常处理

程序或数据错误可能导致硬件异常;如非法指令,总线或地址错误,除0除外,Vxworks异常处理负责这些异常处理。

一般默认处理是将引进异常的任务挂起,保存该任务引起异常时运行状态。 内核和其他任务继续运行。

 代码的共享与重入:

  Vxworks中, 一段子程序可能被多个任务调用,共享代码就是被多个任务执行的代码。共享代码是系统更加有效和易于管理。

Vxworks只要使用一些重入技术:

1. 动态可变堆栈;

2. 信号量对全局变量和静态变量进行保护

3.任务可变

动态可变堆栈:

  许多子程序是纯粹的代码,除了动态可变堆栈外没有他们自己的数据,这些程序是可重入的,因为每个在调用该子程序的任务都有它自己的堆栈区。

全局和静态变量的保护:

 任务可变(task  variables)

  一些被多个任务调用的程序,每个任务可能要求各自独立使用它的全局或静态变量。

Vxworks 提供了taskvariable()可变任务的方法。

Vxworks提供了几个系统任务

 根任务(root task): tUsrRoot

   根任务tUsrRoot 是被内核第一个执行的任务,根任务的进入点式usrRoot,(在config/all/usrConfig.h)并初始化几乎所用的xvworks工具。初始化完成后,根任务将自己删除,

The logging Task :tlogTask

Log任务:tLogtask被vxworks模块用于登陆系统信息。

异常处理任务:tExcTask

   异常处理任务,tExcTask 支持vxworks异常处理,你必须在系统中有最高优先级。不要将该任务挂起,删除或改变优先级。

网络任务:tNetTask

任务间通信:

  Vxworks提供了丰富的机制来 进行任务间通信:

  共享内存;信号量,消息队也和管道,socket(套接字);信号(signals)处理异常

共享数据结构(共享内存)

   互斥

   当一块共享地址空间用来交换数据时,避免冲突很关键,一般用关中断,禁止抢占,信号量锁定资源。

关中断 

   关闭中断后,其它程序就不能抢占cpu;

 函数: intLock() intUnlock()

  注意: 实时系统要求对外界的事件能做出实时响应,如果关闭中断后,就无法保证,建议一般尽量少用,或者关中断时间尽量的短。

禁止优先级抢占

  使用这种方法的高优先级任务不能打断在执行的任务,但可以中断,

函数 :taskLock() taskUnLock( )

这种方法还有缺点,就是即使高优先级任务和共享资源毫无关系式也无法进行抢占执行,这样就和实时性有点冲突, 所以我们要求锁定优先级的时间尽量的短,结果更好的办法是用信号量。

信号量:

 Vxworks中信号量是高优化的,提供了最快的任务间通信机制。信号量解决了互斥和同步问题。

互斥:信号量可以保护共享资源,没有锁定中断和优先级带来的不良后果。

同步:信号量通过外部事件来调整任务的执行。

Wind 提供了三种不同的信号量来解决不通类型的问题

 Binary(两进制):最快,最通用的信号量,在解决同步和互斥问题上最优;

 Mutual-exclusion(互斥信号量):特殊的binary信号量,在解决互斥上最优;优先级传递,安全删除,递归。

Counting:适用于共享资源不止一个情况;

信号量控制:

  Vxworks为不同的信号量设计了相同的控制接口。只创建函数不同,

创建信号量的时候,队列类型要指定,等待信号量的任务依据信号量的类型被放不同的等待队列。

注意:删除信号量要小心,特别是互斥信号量,要避免删除一个信号量的时候有其他任务需要改信号量。

Binary信号量(二进制信号量)

 信号量有两种功能:同步和互斥,

 一个binary信号来那个有两种状态:可利用(full)和不可利用(empty)

用semTake()来获得信号量;如果使用该函数的时候,信号量处于full状态,则调用函数后信号量变为empty,否则根据该信号量的类型把申请信号量的任务挂起到相应的等待队列中。当然如果任务是不等待队列信号,则任务继续执行。

  释放信号来那个semGive()

semBCreate()   创建一个二进制信号量

semMcreate()   创建一个互斥信号量

semCCreate()   创建一个计数器信量

semDelete()    终止信号量

semTake()     获得信号量

semGive()     给出信号量

semFlush()    解锁所有正在等待某信号量的任务

函数原型:

 SEM_ID semBCreate
    (
    int         options,      /* semaphore options */
    SEM_B_STATE initialState  /* initial semaphore state */
    )
 SEM_ID semMCreate
    (
    int options               /* mutex semaphore options */
    )
SEM_ID semCCreate
    (
    int options,              /* semaphore option modes */
    int initialCount          /* initial count */
    )
STATUS semDelete
    (
    SEM_ID semId              /* semaphore ID to delete */
    )
STATUS semTake
    (
    SEM_ID semId,             /* semaphore ID to take */
    int    timeout            /* timeout in ticks */
    )
STATUS semGive
    (
    SEM_ID semId              /* semaphore ID to give */
    )
STATUS semFlush
    (
    SEM_ID semId              /* semaphore ID to unblock everyone for */
    )

互斥功能:

   初始化为full, 可以保护共享资源。

#include<vxworks.h>

#include<semLib.h>

SEM_ID  semMutex;

semMutex = semBCreate(SEM_Q_PRIORITY,SEM_FULL);

//用semTake()和semGive()来获得或释放信号量

semTake(semMutex,WAIT_FOREVER);

critical region .only accessible by a single task at a time;

semGive(semMutex);

同步功能:

  使用同步功能的时候,要把信号量初始化为empty ,当任务后中断发生某事件发生后将调用semGive() 函数将其变为full。

 Example:

#include<vxWorks.h>

#include<semLib.h>

#include<arch/arch/ivarch.h>

SEN_ID syncSem ;

Init(int someIntNum)

{

 intConnect(INUM_TO_IVEC(someIntNum),eventInterruptSvcRout,0);

 syncSem = semBCrea(SEM_Q_FILE,SEM_EMPTY);

taskSpawn(“sample”,100,0,2000,task1,0,0,0,0,0,0,0,0,0);

}

Task1(void)

{

 SemTake(syncSem,WAIT_FOREVER);

 Printf(“task 1 got semaphore /n”);

 

}

eventInterruptSvcRout(void)

{

 semGive(syncSem);

}