接口设计上,简单、没有二义性是必须的。但是简单,则可能带来滥用。
为什么这么说呢?先看一个例子。在vxworks里,共享资源的互斥一般可
通过信号量、锁任务(tasklock/taskunlock--禁止/使能任务调度功能)
,锁中断(intlock/intunlock--关闭/使能中断)来实现。这几个接口,
影响的程度不同,一般的编程手册(包括vxworks的帮助文档),都是建
议首先使用信号量,再就是锁任务,锁中断。但是实际上,锁任务使用的
却是最多的,锁中断一听给人的感觉就是比较高深(都中断了,硬件级别
了),一般就不怎么敢用了。下面看看这三类接口的典型用法:
一、信号量
1,创建一个信号量,pMutex = semMCreate(SEM_Q_PRIORITY,SEM_FULL)
2,进入互斥区时,先获取信号量
funcA()
{
...
semTake(pMutex, WAIT_FOREVER);
共享资源操作;
semGive(pMutex);
...
}
二、锁任务
funcA()
{
...
taskLock();
共享资源操作;
taskUnlock();
...
}
三、锁中断
funcA()
{
...
int status = intLock();
共享资源操作;
intUnlock(status);
...
}
可以看出,同样是达到互斥的情况,锁任务比信号量要容易用的多了。信
号量需要创建,并引入了一个新的类型SEMID, 需要一个全局变量来保存
这个ID值,创建时指明等待队列的类型(SEM_Q_PRIORITY、SEM_Q_FIFO)
,信号量当前状态(空、满),其他属性(优先级继承SEM_INVERSION_SAFE
),足够把人绕晕。
相反,锁任务就非常简单,想用的时候直接调用即可,召之即来
挥之即走。其内部实现也是非常简单的,任务控制块里维护了一个lock计
数,tasklock时加1,taskunlock时减1,调度器运行时,判断当前运行任
务的控制块里计数不为0,则不调度了,可以保证当前任务一直运行下去
。
tasklock会导致不相关的高优先级任务得不到调度,但又有多少
个人关心呢?比如任务的优先级如下:t1 > t2 = t3, t2,t3需要互斥访
问同一个共享资源,使用信号量,t1就绪时是可以抢占得到运行的,但如
果使用了tasklock,t1就绪时是没有办法得到运行的。
你可以说系统只是提供了这个机制,是使用的人错了,但系统没
有从使用的人考虑,提供的机制又如何保证使用正确呢?
问题的困难可能在于vxworks没有区分内核态和用户态,所以,
不像linux,干脆用户态就不允许调用tasklock、intlock之类的接口。(
linux内核态也有禁止抢占和关中断的接口)。所以,从linux角度,
vxworks下本来是用户态程序的,也使用了内核接口,当把这类应用程序
,移植到linux下,则需要付出更大的代价(必须把tasklock替换成信号量
互斥,而且还得仔细考虑引入了新的信号量后是否会与其他信号量造成死
锁,必须非常小心!!)。出来混总是要还的。
接口要简单,但使用者也必须仔细考量,不能滥用这个简单的接
口。
为什么这么说呢?先看一个例子。在vxworks里,共享资源的互斥一般可
通过信号量、锁任务(tasklock/taskunlock--禁止/使能任务调度功能)
,锁中断(intlock/intunlock--关闭/使能中断)来实现。这几个接口,
影响的程度不同,一般的编程手册(包括vxworks的帮助文档),都是建
议首先使用信号量,再就是锁任务,锁中断。但是实际上,锁任务使用的
却是最多的,锁中断一听给人的感觉就是比较高深(都中断了,硬件级别
了),一般就不怎么敢用了。下面看看这三类接口的典型用法:
一、信号量
1,创建一个信号量,pMutex = semMCreate(SEM_Q_PRIORITY,SEM_FULL)
2,进入互斥区时,先获取信号量
funcA()
{
...
semTake(pMutex, WAIT_FOREVER);
共享资源操作;
semGive(pMutex);
...
}
二、锁任务
funcA()
{
...
taskLock();
共享资源操作;
taskUnlock();
...
}
三、锁中断
funcA()
{
...
int status = intLock();
共享资源操作;
intUnlock(status);
...
}
可以看出,同样是达到互斥的情况,锁任务比信号量要容易用的多了。信
号量需要创建,并引入了一个新的类型SEMID, 需要一个全局变量来保存
这个ID值,创建时指明等待队列的类型(SEM_Q_PRIORITY、SEM_Q_FIFO)
,信号量当前状态(空、满),其他属性(优先级继承SEM_INVERSION_SAFE
),足够把人绕晕。
相反,锁任务就非常简单,想用的时候直接调用即可,召之即来
挥之即走。其内部实现也是非常简单的,任务控制块里维护了一个lock计
数,tasklock时加1,taskunlock时减1,调度器运行时,判断当前运行任
务的控制块里计数不为0,则不调度了,可以保证当前任务一直运行下去
。
tasklock会导致不相关的高优先级任务得不到调度,但又有多少
个人关心呢?比如任务的优先级如下:t1 > t2 = t3, t2,t3需要互斥访
问同一个共享资源,使用信号量,t1就绪时是可以抢占得到运行的,但如
果使用了tasklock,t1就绪时是没有办法得到运行的。
你可以说系统只是提供了这个机制,是使用的人错了,但系统没
有从使用的人考虑,提供的机制又如何保证使用正确呢?
问题的困难可能在于vxworks没有区分内核态和用户态,所以,
不像linux,干脆用户态就不允许调用tasklock、intlock之类的接口。(
linux内核态也有禁止抢占和关中断的接口)。所以,从linux角度,
vxworks下本来是用户态程序的,也使用了内核接口,当把这类应用程序
,移植到linux下,则需要付出更大的代价(必须把tasklock替换成信号量
互斥,而且还得仔细考虑引入了新的信号量后是否会与其他信号量造成死
锁,必须非常小心!!)。出来混总是要还的。
接口要简单,但使用者也必须仔细考量,不能滥用这个简单的接
口。