Linux终端初始化和tty驱动框架

描述

initcall机制

注意上述流程,我们来理解一下 initcall 机制:

普通我们写一个程序,想要它被调用,需要在主流程中调用这个函数,才算被调用。

那么这种方式如果放在 Linux 中,是难以想象的,我们自己写的代码要在多少个地方声明。

而你如果采用initcall机制,意思就是说,你使用一个字符串声明你的驱动初始化函数,那么所有的驱动初始化函数都存在内存中一个连续的段中,系统启动以后,会从这个段的第一个函数开始,一个一个遍历,进而一个一个调用,这就是initcall 机制。这就是为什么我们写驱动只需要使用 module_init 声明,编译进去即可自动被调用的原因!!!

System.map

编译后的内核根目录 System.map 文件记载了所有的驱动加载顺序,如果你不确定驱动的加载顺序,在这里查看就可以,每次编译 Linux 内核就会产生一个新的 System.map。

tty 驱动

我们不要把 tty 驱动和 串口驱动 弄混了,tty 驱动架构如下:

终端

其中 tty driver 等价于我们普通写的驱动,可以自己写。

也就是说,在 tty 驱动框架主要有三层:tty core、tty line discipline、tty driver,另外最上层是用户空间,最下层是硬件。

tty core 称之为 tty 核心,主要作用是向用户提供统一的接口。

tty line discipline 称之为 tty 线路规程,主要从上下两层接收数据,并按照一定协议进行转换,比如 ppp 或者蓝牙协议,这样你的tty 终端就不止可以用普通的串口,还可以通过其他协议访问到我们的系统。比如手机链接 PCB 板子的 WiFi 接入系统控制终端,输入 ls、cd等命令。这一层并不是必须的,你可以直接使用驱动和 tty core 进行通信,但一般这一层都会有。

tty driver 就是我们常说的串口驱动。

在 console_init 函数中,它做的两件事,就是注册 tty 线路规程,注册 tty 驱动,tty 核心是包含在内核当中的。tty 线路规程和tty 驱动可以有很多个。

有的人会有疑问,为什么有了 tty 驱动了,还会有一个 tty 线路规程。得益于 Linux 模块化的思想,这里主要是为了分层与隔离。tty驱动只和硬件相关,只解析基本的硬件信息,把硬件信息转换成字符。所有的对字符的进一步处理包括加入蓝牙协议传输,监控数据等都放在 tty 线路规程当中。这样 tty
驱动是可以完美复用和移植的。

分享一张彭大佬的图,本文我只讲了概念,彭大佬讲解过 tty 源码:

终端

这里只需要注意一点,在右下角,tty driver 是没有 read 函数的,tty driver 层有 buffer,输入的数据会存储在buffer 中,被读取。

原因很简单,对于 tty 来说,输入设备和输出设备不是同一个设备,输入设备是键盘,输出设备是屏幕,这和普通的 IIC、SPI驱动同一个设备不一样。因此在设计上 tty driver 没有 read 函数。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分