该篇主要用来分析TTY
子系统的框架,TTY
框架图如下:
TTY
子系统位于标准字符驱动之下,其中包括:TTY核心层,TTY线路规程,TTY驱动层。
TTY Core
:该核心层主要负责控制跨越一个tty
设备的数据流和数据格式,使得TTY Driver
能够以一致的方式处理 到硬件 和 出自硬件 的数据。
TTY Line Discipline
:线路规程,以特殊的方式对数据进行二次加工,通常表现为协议的转换,如:PPP
和Bluetooth
,以便可以虚拟的“插入”到任何tty
设备。
TTY Driver
:该层主要用于实现各类终端的驱动,用以控制实际硬件设备,用于收发数据。其有3种不通类型的驱动:**控制台,串口,pty
**。其中,控制台和 pty
驱动已经被编写进内核。
下面是在网上的另一个TTY
框架图,结合上图更加方便理解:
从上往下看,最上面是应用层,其次是字符设备驱动,然后是TTY核心层,TTY驱动层。
其中,
用户层:在用户空间,我们操作TTY
的方法就是通过open
,read
,write
读写设备文件,如:/dev/tty
、/dev/console
等
通用字符设备驱动:对上,以字符设备驱动的形式,向应用程序提供统一接口open, read, write
,以便输入输出数据
System Console Core
:其主要有两个功能:
1)向系统提供控制台终端(Console Terminal) ,以便让用户登录进行交互操作。
2)提供printk功能,以便kernel代码进行日志输出。
System console core
模块使用struct console结构抽象system console功能,具体的driver不需要关心console的内部逻辑,填充该接口并注册给kernel即可。
ketnel
│ └── driver
│ │ └── tty
│ │ │ └── serial # 串口终端驱动
│ │ │ │ └── 8250
│ │ │ │ │ ├── 8250_core.c # 8250 串口核心层
│ │ │ │ │ ├── 8250_port.c # 8250 串口port抽象
│ │ │ │ │ ├── 8250_dma.c # 8250 dma驱动
│ │ │ │ │ ├── 8250_dw.c # 8250 device driver抽象
│ │ │ └── vt # 虚拟终端驱动
│ │ │ └── ipwireless # 无线终端驱动
│ │ │ └── hvc # 虚拟控制台
│ │ │ ├── tty_xxx #tty driver port 抽象
│ │ │ ├── n_xxx.c # tty line discipline 线路规程相关文件
serial
:该目录下为串口终端的驱动程序
hvc
:hypervisor虚拟控制台
vt
:目录下为虚拟终端的驱动程序
n_xxx.c
:为线路规程的相关文件,也就是串口数据处理
tty_xxx
:包括字符设备驱动的实现,ioctl
等
8250_xxx
:为serial Driver
TTY
是所有终端的统称,对于不同的终端,我们有不同的驱动程序,那么我们怎么知道当前系统中,哪个驱动被加载,哪个终端设备存在呢?
可以查看/proc/tty/drivers
文件,这个文件可以包含当前存在的,不同tty
驱动的列表,驱动的名字,驱动的主编号,次编号范围,tty
驱动的类型。
/dev/tty /dev/tty 5 0 system:/dev/tty
/dev/console /dev/console 5 1 system:console
/dev/ptmx /dev/ptmx 5 2 system
/dev/vc/0 /dev/vc/0 4 0 system:vtmaster
usbserial /dev/ttyUSB 188 0-254 serial
serial /dev/ttyS 4 64-67 serial
pty_slave /dev/pts 136 0-255 pty:slave
pty_master /dev/ptm 128 0-255 pty:master
pty_slave /dev/ttyp 3 0-255 pty:slave
pty_master /dev/pty 2 0-255 pty:master
unknown /dev/tty 4 1-63 console
所有当前注册的以及在内核中出现的tty
设备,有他们自己的子目录 /sys/class/tty
下面。
在他们
tty
设备的子目录下面的文件夹中,有一个dev
文件,包含了分配给tty
设备的主次编号。如果驱动程序告诉内核与tty设备相关联的物理设备和驱动程序的位置,它就会创建回这些位置的符号链接。
/sys/class/tty/
|-- console
| `-- dev
|-- ptmx
| `-- dev
|-- tty
| `-- dev
|-- tty0
| `-- dev
...
|-- ttyS1
| `-- dev
|-- ttyS2
| `-- dev
|-- ttyS3
| `-- dev
...
|-- ttyUSB0
| |-- dev
| |-- device -> ../../../devices/pci0000:00/0000:00:09.0/usb3/3-1/3-1:1.0/ttyUSB0
| `-- driver -> ../../../bus/usb-serial/drivers/keyspan_4
|-- ttyUSB1
| |-- dev
| |-- device -> ../../../devices/pci0000:00/0000:00:09.0/usb3/3-1/3-1:1.0/ttyUSB1
| `-- driver -> ../../../bus/usb-serial/drivers/keyspan_4
|-- ttyUSB2
| |-- dev
| |-- device -> ../../../devices/pci0000:00/0000:00:09.0/usb3/3-1/3-1:1.0/ttyUSB2
| `-- driver -> ../../../bus/usb-serial/drivers/keyspan_4
`-- ttyUSB3
|-- dev
|-- device -> ../../../devices/pci0000:00/0000:00:09.0/usb3/3-1/3-1:1.0/ttyUSB3
`-- driver -> ../../../bus/usb-serial/drivers/keyspan_4
每个tty
设备都有一个struct cdev
,以便用户空间可以访问。
/dev/tty
/dev/console
/dev/ttyS0
OK,
TTY
子系统框架以及目录结构分析就先了解到此,后续分析其主要的数据结构!