刚开始学习ldd3时,驱动架构以为是围绕这device,device_driver,bus,等等建立起来的。确实是这样,通过这样在内核建立了一个驱动框架去管理它们。然而却错误的理解为实际的驱动硬件的工作也是在那几个结构上,大错特错。举个例子,像块设备驱动,操作硬件工作是在gendisk结构里面实现的,通过register_disk,则可以根据disk里面的设备号在内核建立起device,sysfs,devfs里面的模型。而内核在操作一个块设备时是通过block_device,这个结构跟device,device_driver那些驱动架构的数据结构没有半毛钱关系,它只是跟disk挂钩,而这个block_device是嵌入在inode结构里面。内核真正操作设备是根据相应设备文件的inode,block_device,disk,bio,address_space等等来操作的。但这些结构不是平白无故的得来的,正式通过注册设备驱动,通过device,device_driver,bus,sysfs这些玩意在内核建立架构,在与那些真正的操作设备的block_device,disk建立起很微妙的关系。在打开一个设备时,会跟据在内核的已经注册的信息,来初始化block_device,inode等等。所以ldd3上所述的驱动模型是上层的比较抽象的,用来管理真正的设备驱动,像device_driver,里面只包括一些probe,suspend,resume,shutdown,remove,还有一些电源管理方法,这都是一些比较上层的操作,还有一些将device,device_driver封装的像platform_driver,platform_device,pci_dev,pci_driver,等等是对设备的分类吧,易于管理。
对于每一种设备,在内核的模型和真实的硬件驱动建立起的关系都不同,但总体思路差不多。例如tty驱动。操作一个物理串口是,经过tty_core->line_disc->tty_driver,注册一个物理串口驱动时,相应的ops会赋值给tty_driver里面。例如
int uart_register_driver(struct uart_driver *drv)}
uart_driver会调用串口的底层驱动,uart_port里面的ops是底层驱动。
uart_port是在probe过程中赋值给tty_driver里面的。
用户信息输出到串口流程,file_ops=tty_ops tty_ops-> tty_sturct->ldisc->write -> tty_driver->write.
tty_core--->tty_ldisc--->tty_driver--->uart_driver--->uart_port这条路线是不动的,封装好的对于不同的串口驱动,例如在一个xxxx.c文件里面,对于的串口的各种操作如设置,发送,接收都会封装在uart_ops里面,注册驱动后,probe函数会将uart_ops赋给上层的uart_port进而与tty核心连接起来,对于不同的设备,我们只要设计自己的xx_uart_druver,uart_port,不用管tty层。uart_port就是对应一个物理串口,包括串口的各种属性与ops,它会呗注册。
uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)--> tty_register_device(drv->tty_driver, uport->line, uport->dev).
tty线程规程以特殊的方式格式化从一个用户或者硬件收到的数据,这种格式化常常采用一个协议转换的形式,如PPP、Bluetooth。
tty设备驱动到串口驱动中间经过了一层serial_core
对于tty驱动层主要有几个重要的结构
serial_core实现了UART设备的通用TTY驱动层(称为串口核心层),这样UART驱动的主要任务演变成了实现serial_core中定义的一组uart_xxx接口而非tty_xxx接口,见如下的对应关系
----------------设备方法-----------------------------设备注册------------------------设备信息
------------tty_operations------------------------tty_driver---------------------------tty-struct // tty核心层定义,)
+ + +
+ + +
--------------uart_ops-----------------------------uart_driver---------------------------uart_port // 串口核心层定义serial_core.c(串口核心层实现的结构体