字符设备的定义
linux下有三种设备:字符设备、块设备、网络设备等等。它们均以一个文件节点形式显示在文件系统的/dev
目录下(crw--w---- 1 root tty 4, 0 7月 11 09:11 tty0
其中c代表字符设备类型)。
字符设备是指设备无需缓冲即可直接进行读写的设备, 如鼠标,键盘,串口设备等, 它与块设备的区别在于是字符操作的基本单位是字节。下面为字符设备结构示意图:
字符设备的性质及特点
-
字符设备属于设备文件系统的一种, 相当于底层硬件向上层提供的逻辑设备文件, 宛如将一个数据端口(数据寄存器)与一个文件对接起来,设备驱动程序直接对文件操作, 于是便直接对端口进行了读写操作。 同样作为文件, 字符设备驱动也必须实现文件的基本的操作open(),close(),write(),read()等,当然终端重定向操作也是支持的。
-
字符设备文件文件的读写是以单个字节为单位的, 不需要设立硬件缓冲区。 设备像访问字节流一样被操作系统访问。 字节流就像在硬件端口和文件系统搭建起了一个传送管道, 字节逐个通过管道传输并呈现给读写双方。 这个流特性在驱动程序中是以缓冲队列来实现的。例如: 控制台的结构体中的读写缓冲队列
struct tty_struct { struct termios termios; int pgrp; int stopped; void (*write)(struct tty_struct * tty); struct tty_queue read_q; //读队列 struct tty_queue write_q; //写队列 struct tty_queue secondary; //tty辅助队列(存放规格化后的字符) };
-
字符设备由字符设备号标识。字符设备号由主设备号和次设备号构成, 例如/dev/ttyS0的设备号为(4,64); 主设备号标识设备对应驱动程序, 内核通过主设备号将设备和驱动程序一一对应起来, 次设备号由驱动程序使用, 用于驱动程序内部区分设备细节差别使用的代码,内核其他部分不使用它。
字符设备的分类
字符设备主要包括控制终端设备和串行终端设备, 例如控制台和键盘。依据功能和硬件上的差别, 字符终端设备有如下分类:
- 串行端口终端(
/dev/ttSn
):使用计算机串行端口连接的终端设备, 串行设备数据传输方式为同一字符8个bit单线传输, 在命令行输入echo 'hello world' > /dev/ttyS0
可将输入写入到对应设备。 - 伪终端(
/dev/ttyp,/dev/ptyp
): 对应底层不存在真实的硬件设备, 用于为其他程序提供终端式样的接口,如网络登陆主机时网络服务器和shell程序之间的终端接口。 - 控制终端(
/dev/tty
):主设备号为5, 进程控制终端,与进程相关联,如登陆shell进程使用的就是终端/dev/tty
。 - 控制台(
/dev/ttyn,/dev/consol
): 计算机输入输出的显示器,当控制台登陆时, 使用的就是tty1, 而ubuntu 图形界面使用的tty7。 - 其他类型:现行的linux针对许多不同的设备建有许多其他种类的设备特殊文件,如ISIDIN设备的/dev/ttyIn设备。
具体分类可参看http://www.cnblogs.com/yxmx/articles/1612627.html
字符设备与驱动程序的关系
字符设备与驱动程序的处在不同的层次上, 驱动程序实现了对硬件的控制逻辑, 并将其以统一接口的形式呈现给上层用户。
这样的话, 字符设备驱动程序就是硬件和文件组织系统间的接口, 它或解释底层硬件中断, 翻译并转交给用户进程, 或将用户进程发出的信号传输给硬件, 触发硬件中断。
例如,当用户在键盘上键入了一个字符时,会引起键盘中断响应(中断请求信号 IRQ1, 对应中断号INT 33 ),此时键盘中断处理程序就会从键盘控制器读入对应的键盘扫描码,然后根据使用的键盘扫描码映射表译成相应字符,放入 tty 读队列 read_q 中。然后调用中断处理程序的 C 函数 do_tty_interrupt()
,并调用写控制台函数 con_write()
。此时如果该终端的回显( echo )属性是设置的,则该字符会显示到屏幕上。
并且, 进程对字符设备的读写通过文件系统实现的文件读写操作从用户缓冲区读取一个字符写入写队列, 若写队列已满, 则将写队列输出到控制台显示出来。
整个操作过程见图 7-3 所示 :