vxworks下怎样使驱动支持select机制
来源:互联网 发布:apache无法访问根目录 编辑:程序博客网 时间:2024/05/22 10:45
当有如下几种情况发生时,需要考虑使驱动支持 select机制:
· 任务声明一个超时机制来等待设备I/O。一个UCP socket任务需要设定一个超时机制来等待一个数据包的到来。
· 驱动支持多个设备,任务可以等待他们其中的任何一个。例如:多个管道可用被用于不同的数据优先级。
· 任务等待不同的I/O设备。例如:服务进程可能同时使用pipes和sockets。
要想使一个设备支持select机制,首先要声明SEL_WAKEUP_LIST 结构体,这个结构体统称被定义为设备描述符的一部分, xxDevCreate( ) 函数调用selWakeupListInit( )来初始化这个结构体。当任务调用 select( ),selectLib 将会调用哪个设备函数ioctl( )中的FIOSELECT 或FIOUNSELECT 。
对于FIOSELECT, 设备执行如下操作:
1. Add the SEL_WAKEUP_NODE (providedas the third argument of ioctl( )) to the SEL_WAKEUP_LIST bycalling selNodeAdd( ).
2. Use the routine selWakeupType( ) to checkwhether the task is waiting for data to read from the device (SELREAD) or if thedevice is ready to be written (SELWRITE).
3. If the device is ready (for reading orwriting as determined by selWakeupType( )), the driver calls the routine selWakeup( ) to make surethat the select( ) call in thetask does not pend. This avoids the situation where the task is blocked but thedevice is ready.
对于FIOUNSELECT ,函数执行selNodeDelete( ) ,将SEL_WAKEUP_NODE 从wakeup链表中删除。
当设备可以使用时,调用selWakeupAll 解锁所有等待该设备的任务,这个在设备的ISR中使用的比较广泛,但在其他的地缝也是可以使用的。
select()的作用应该是这样的:
1.由任务调用select():
void myTask()
{
...
select(width, readFds, writeFds, exceptFds, timeout);
...
}
select()意思是说:若readFds集合中的任一个fd可读,或writeFds中的任一个fd可写,或exceptFds中的任一个fd出异常(目前VxWorks还不支持),或者timeout指定的时间超时,则select()返回;否则任务myTask()处于阻塞状态,直到上述的条件之一得到满足。
2. select()的伪代码“可能”类似于:
select()
{
// selWakeupNode结构可能是malloc得到的,或者静态的。不清楚。
selWakeupNode->taskId = taskIdSelf();
selWakeupNode->type= SELREAD;
for (each fd in readFds)
ioctl(fd, FIOSELECT, (int)selWakeupNode);
selWakeupNode->type= SELWRITE;
for (each fd in writeFds)
ioctl(fd, FIOSELECT, (int)selWakeupNode);
semTake(tcb->semSelect,timeout); // 进入阻塞状态;睡觉去了
selWakeupNode->type= SELREAD;
for (each fd in readFds)
ioctl(fd, FIOUNSELECT, selWakeupNode);
selWakeupNode->type= SELWRITE;
for (each fd in writeFds)
ioctl(fd, FIOUNSELECT, selWakeupNode);
}
FIOSELECT命令是告诉驱动程序:“我对您设备的可读/可写感兴趣,请在满足条件时务必通知我。别忘了,我叫selWakeupNode->taskId,我对selWakeupNode->type感兴趣。”
睡眠醒来后,任务又说:“ok,都别管我了。”
3. (2)中的每一个ioctl调用都会转换为和fd相关联的驱动程序的xxIoctl()的调用:
xxIoctl(pXxDev,<I>function</I>, arg)
{
switch (<I>function</I>) {
...
case FIOSELECT:
if ((retval = selNodeAdd(&pXxDev->selWakeupList, // 可能有多个任务要处理,用链表记住它们
(SEL_WAKEUP_NODE *)arg)) == OK) {
if ((selWakeupType(arg) == SELREAD && ‘当前可读’) ||
(selWakeupType(arg) == SELWRITE && ‘当前可写’))
selWakeup(arg); // 不用等待,醒来吧
}
return retval;
caseFIOUNSELECT: // 该任务对我不感兴趣了...
return selNodeDelete(&pXxDev->selWakeupList,
(SEL_WAKUP_NODE *)arg);
...
}
}
字符设备(character device)驱动程序如果要支持select,必须处理FIOSELECT和FIOUNSELECT命令。一般在设备控制结构中定义select-wakeup-list,并在创建设备时初始化。
4. xx设备在发生中断时,ISR被调用:
xxInt(pXxDev)
{
// 读状态寄存器
if (''接收到数据'') // 可读
selWakeupAll(&pXxDev->selWakeupList, SELREAD);
if (''数据已发送'') // 可写
selWakeupAll(&pXxDev->selWakeupList, SELWRITE);
...
}
中断函数中根据情况唤醒所有等待可读/可写的任务。selWakeup()和selWakeupAll()都是I/O系统中的函数,看不到源码。猜想它们的伪码如下:
selWakeup(node)
{
semGive(node->taskId->semSelect); // 唤醒等待的任务
}
selWakeupAll(list,type)
{
for (each node in list)
if (node->type == type)
semGive(node->taskId->semSelect); // 唤醒等待的任务
}
- vxworks下怎样使驱动支持select机制
- vxworks下select()的使用
- vxworks下select()的使用 .
- 对于vxworks下硬盘驱动
- 驱动支持select函数
- 2440下vxWorks DM9000A网卡驱动移植
- Vxworks下flash驱动编写流程
- Vxworks下flash驱动编写流程 .
- VxWorks下USB驱动总结1
- VxWorks下USB驱动总结2
- vxWorks下intel82567v3网卡驱动的更新
- vxworks下基于select的TCP服务器端设计
- vxworks下基于select的TCP服务器端设计
- select和poll实现及驱动支持
- python 3下基于select模型的事件驱动机制程序
- vxworks操作系统图形模式下显示驱动设计
- FreeScale mpc8xxx + vxWorks平台下spi flash驱动开发三步走
- FreeScale mpc8xxx + vxWorks平台下spi flash驱动开发三步走
- PHP中create_function的用法总结
- MFC多文档
- 快速排序中对指针地址所指向的值进行排序的代码
- PHP中的错误处理和日志函数
- struts2 拦截器 interceptor
- vxworks下怎样使驱动支持select机制
- 何时提炼函数 & 用查询取代临时变量
- android 耳机插入检测
- Android异步加载图像小结 (含线程池,缓存方法)
- VBA 查找特定值并选中整行
- PHP访问MySql数据库 中级篇 Smarty技术
- 设计模式--工厂设计(2)
- 解决spring mvc JSON 无限死循环
- 学习C#