字符输入输出

| 暂无评论 | 暂无引用通告

  高性能字符输入输出是任何实时操作系统的关键需求之一。字符设备可以定义为字节序列串行输入输出的设备,与其对应的就是基于块传输的设备(例如磁盘驱动器)。

  依照UNIX的传统,这些字符设备位于操作系统路径空间的/dev目录下。例如,一个能够连接调制解调器或终端的串口可能在系统中是这样描述的:

/dev/ser1

  计算机中的典型字符设备硬件包括了:

  • 串口
  • 并口
  • 文本终端
  • 伪终端(ptys)

  程序可以使用标准的open()、close()、read()和write()这些API函数来访问这些字符设备。除此之外,对于操控这些字符设备的其他参数(例如波特率、流控制、奇偶校验等)还有附加的函数可以调用。

  由于通常都使用多个字符设备,这些字符设备的驱动设计就成为一个系列家族并有一个叫做io-char库来实现代码的复用最大化。

  io-char模块中包含了支持POSIX对这些设备操作语法的全部代码。另外它还包含了大量的在POSIX之外的但是又是实时系统所需要的代码,用来完成实现字符设备的特殊功能。由于这些代码都在这个通用库里面,所有的驱动就继承了这些功能。

  驱动就是调用库中函数的执行进程。在实际操作中,驱动首先启动并激活io-char。驱动本身就像其他的UNIX进程一样,并能够根据所操作的硬件的特性以及客户端请求服务来运行在不同的优先级上。

  一个字符设备开始运行之后,再添加附加设备的内存开销就是极小的了,因为只有完成新驱动架构的代码是新的。

驱动与io-char的通讯

  io-char库管理着应用程序与设备驱动之间的数据流动。io-char与驱动之间的数据流动是通过一组依附于每个字符设备的内存队列实现的。

  每个驱动使用了三个队列。每个队列都是使用先入先出(FIFO)机制实现的。

  接收到的数据被驱动放入raw输入队列,并只有在应用程序进程请求数据时才会被io-char所消耗。

  驱动程序中的中断处理程序通常调用io-char中的一个可信任库存程序来将数据加到这个队列上——这就确保了有一个一致的输入规程并最小化驱动的责任(以及创建新驱动所需要的工作)。

  io-char模块将输出数据放入输出队列中,这些数据将会被驱动程序所消耗,并将这些字符传送到实际设备。这个模块在每当新数据被添加时调用驱动程序中的可信任例程来让驱动程序执行操作。由于使用了输出队列,io-char对所有字符设备使用了后写机制(write-behind)。只有在输出缓存满的时候,io-char才在一个进程执行写操作时将其阻塞。

  正则队列(canonical queue)全部由io-char模块所管理,并在编辑模式下处理输入数据的时候使用。这个队列的大小决定了对于某个特定设备所能处理的最大可编辑输入行。

  队列的大小可以通过命令行选项进行设置。默认值是足够应付大多数硬件的配置了,不过你可以对其调整来降低总体的系统内存需求,适应特殊硬件状态或者是处理独特的协议需求。

  设备驱动的动作都比较简单,包括了将接收到的数据放入raw输入队列或消耗并传送输出队列中的数据。io-char模块则是决策何时或是否挂起输出传输、如何或是否响应接收到的数据等等。

设备控制

  低级的设备控制是通过devctl()函数来实现的。POSIX的终端控制函数是架构在devctl()函数之上的。这些POXIS函数包括了:

tcgetattr()  获取终端属性;
tcsetattr()  设置终端属性;
tcgetpgrp()  获取一个终端的进程群头的ID;
tcsetpgrp()  设置一个终端的进程群头的ID;
tcsendbreak()  设置中断条件;
tcflow()  挂起或重启数据传送/接收。

QNX对这些终端控制API的扩展如下:

tcdropline() 断开连接的初始化。对于串口设备来说,这将在DTR线上发送脉冲;
tcinject() 在正则缓存中注入字符。

  io-char模块直接对大多数驱动支持的devctl()命令进行操作。应用程序通过io-char模块向驱动程序发送设备特定的devctl()命令。

暂无引用通告

发送引用通告网址: http://www.eggheader.com/mtos/mt-tb.cgi/30
如果你想引用这篇文章到你的Blog,请复制上面的链接,放置到你发表文章时的相应界面中。

发表评论