TTY设备驱动结构( 二 )


关键数据结构
[tty设备驱动子系统]由三个主要的数据结构构建:
:这是[tty设备]的核心表征数据结构,结构体内内嵌(通过指针)余下的两个关键数据结构 。每当有新的tty设备被打开使用时,都被创建一个新实例,直到设备被关闭 。注意实际代码里(.c)有很多复杂的操作,例如在打开和关闭tty设备的过程中对的设定的保存与恢复(至少基于串口的tty设备如此) 。
:这是驱动本身的表征,定义设备号,定义并实现设备的使用接口等,在设备打开的时,函数负责关联设备与设备驱动 。结构成员大略如下:
struct tty_driver {/* the driver states which range of devices it supports */short major;/* major device number */short minor_start;/* start of minor device number*/shortnum;/* number of devices *//* and has its own operations */int(*open)();void (*close)();int(*write)();int(*ioctl)();/* device-specific control *//* return information on buffer state */int(*write_room)();/* how much can be written */int(*chars_in_buffer)(); /* how much is there to read *//* flow control, input and output */void (*throttle)();void (*unthrottle)();void (*stop)();void (*start)();/* and callbacks for /proc/tty/driver/ */int (*read_proc)();int (*write_proc)();};
:线路规则模块由的ldisc域指定 。在设备打开的时候,ldisc默认指向n_tty,用户空间程序可以通过ioctl切换tty设备的线路规则 。结构成员大略如下:

TTY设备驱动结构

文章插图
struct tty_ldisc {/* routines called from above */int(*open)();void(*close)();ssize_t (*read)();ssize_t (*write)();int(*ioctl)();/* routines called from below */void(*receive_buf)();int(*receive_room)();void(*write_wakeup)();};
作为一般的tty设备驱动程序开发者,可以不必关心的实现,只管 和 就行了 。因为当应用系统使用新串行通信设备,我们一般实现就行了;如果应用系统有传统的串口,并且想开发新上层应用,那实现一支新线路规则模块就行了 。例如,假设你手头有一块特殊的键盘,使用标准RS-232串口,那么需要实现一支新线路规则模块就可以了,因为整套的串口tty设备驱动有了,键盘驱动已经有了 。新线路规则模块完成与input子系统和通用键盘驱动的通信 。
设备的读写数据流
3
图三展示了数据是如何从用户空间流向硬件接口并返回的 。从图可知,“写入数据”是比较直观,“读出数据”需要解释一下 。“读数据”稍微复杂,因为“读数据”时硬件和用户空间没有直接的调用关系 。因为只有用户空间调用硬件,硬件不能调用用户空间代码,所以只能把收到的数据存放起来,等用户空间程序来读 。你可能已经猜到解决办法——使用缓冲区:硬件收到的数据会存放到内核的缓冲区并保持着,直到有用户空间程序把它们读走 。当某用户程序读取缓冲区,而缓冲区为空的时候,用户程序被置入睡眠状态,只有当缓冲区收到数据后才被唤醒 。
注意,其实“写数据”的操作一样有缓冲区 。只是“写操作”是一步接一步由上而下,控制流比较简单直接,不像读操作有数据传输的延迟,写操作的缓冲区只是为了“软化”硬件传输操作和软件控制操作的边界 。为了精简图示,图中没有画出写操作缓冲区 。
对tty设备而言,[读缓冲区]应该集成在tty的数据结构内,虽然这样设计会让变得相当肥大,但是没有理由表明缓冲区可以放在其它地方 。tty设备传输不能没有缓冲,而tty设备是动态创建的,所以即使缓冲占有空间,至少不会浪费空间 。
tty设备被设计使用两种类型的缓冲区,内核开发者选择了在线路规则模块内使用普通的缓冲区(tty ),而低层硬件驱动使用翻转式缓冲区(),使用翻转式缓冲,硬件驱动可以尽可能快的接收传入的数据,不必与上层同步操作:由硬件独占使用,的数据被函数转存入tty。