Linux设备模型之tty驱动架构分析.pdf
《Linux设备模型之tty驱动架构分析.pdf》由会员分享,可在线阅读,更多相关《Linux设备模型之tty驱动架构分析.pdf(16页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Linux 设备模型之设备模型之 tty 驱动架构分析驱动架构分析 一:前言 Tty 这个名称源于电传打字节的简称。在 linux 表示各种终端。终端通常都跟硬件相对应。比如对应于输入设备键盘鼠标。输出设备显示器的控制终端和串口终端.也有对应于不存在设备的 pty 驱动。在如此众多的终端模型之中,linux 是怎么将它们统一建模的呢?这就是我们今天要讨论的问题.二:tty 驱动概貌 Tty 架构如下所示:如上图所示,用户空间主要是通过设备文件同 tty_core 交互.tty_core 根据用空间操作的类型再选择跟 line discipline 和tty_driver 交互.例如设置硬件的
2、ioctl 指令就直接交给 tty_driver 处理。Read 和 write 操作就会交给 line discipline 处理.Line discipline 是线路规程的意思。正如它的名字一样,它表示的是这条终端”线程”的输入与输出规范设置.主要用来进行输入/输出数据的预处理。处理之后。就会将数据交给 tty_driver Tty_driver 就是终端对应的驱动了。它将字符转换成终端可以理解的字串.将其传给终端设备。值得注意的是,这个架构没有为 tty_drivero 提供 read 操作。也就是说 tty_core 和 line discipline 都没有办法从 tty_driv
3、er里直接读终端信息。这是因为 tty_driver 对就的 hardware 并不一定是输入数据和输出数据的共同负载者。例如控制终端,输出设备是显示器。输入设备是键盘。基于这样的原理。在 line discipline 中有一个输入缓存区。并提供了一个名叫 receive_buf()的接口函数。对应的终端设备只要调用 line discipine 的 receiver_buf 函数,将数据写入到输入缓存区就可以了。如果一个设备同时是输入设备又是输出设备。那在设备的中断处理中调用 receive_buf()将数据写入即可.三:tty 驱动接口分析 具体的 tty 驱动设计可以参考 LDD3。这
4、里只对它的接口实现做一个分析.tty driver 的所有操作都包含在 tty_driver 中。内核即供了一个名叫 alloc_tty_driver()来分配这个 tty_driver。当然我们也可以在自己的驱动中将它定义成一个静态的结构。对tty_driver 进行一些必要的初始化之后,调用 tty_register_driver()将其注册.alloc_tty_driver()接口代码如下所示:struct tty_driver*alloc_tty_driver(int lines)struct tty_driver*driver;driver=kzalloc(sizeof(struct
5、 tty_driver),GFP_KERNEL);if(driver)driver-magic=TTY_DRIVER_MAGIC;driver-num=lines;/*later well move allocation of tables here*/return driver;这个函数只有一个参数。这个参数的含义为 line 的个数。也即次设备号的个数。注意每个设备文件都会对应一个 line.在这个接口里为 tty_driver 分配内存,然后将 driver-mage.driver-num 初始化之后就返回了.tty_register_driver()用来注册一个 tty_driver。
6、代码如下:int tty_register_driver(struct tty_driver*driver)int error;int i;dev_t dev;void*p=NULL;/TTY_DRIVER_INSTALLED:已安装的 if(driver-flags&TTY_DRIVER_INSTALLED)return 0;/TTY_DRIVER_DEVPTS_MEM:使用 devpts 进行动态内存映射 if(!(driver-flags&TTY_DRIVER_DEVPTS_MEM)&driver-num)p=kzalloc(driver-num*3*sizeof(void*),GFP_
7、KERNEL);if(!p)return-ENOMEM;/注册字符设备号 /如果没有指定 driver-major if(!driver-major)error=alloc_chrdev_region(&dev,driver-minor_start,driver-num,driver-name);if(!error)driver-major=MAJOR(dev);driver-minor_start=MINOR(dev);else dev=MKDEV(driver-major,driver-minor_start);error=register_chrdev_region(dev,driver
8、-num,driver-name);if(error ttys=(struct tty_struct*)p;driver-termios=(struct ktermios*)(p+driver-num);driver-termios_locked=(struct ktermios*)(p+driver-num*2);else driver-ttys=NULL;driver-termios=NULL;driver-termios_locked=NULL;/注册字符设备 cdev_init(&driver-cdev,&tty_fops);driver-cdev.owner=driver-owner
9、;error=cdev_add(&driver-cdev,dev,driver-num);if(error)unregister_chrdev_region(dev,driver-num);driver-ttys=NULL;driver-termios=driver-termios_locked=NULL;kfree(p);return error;/指定默认的 put_char if(!driver-put_char)driver-put_char=tty_default_put_char;mutex_lock(&tty_mutex);list_add(&driver-tty_drivers
10、,&tty_drivers);mutex_unlock(&tty_mutex);/如果没有指定 TTY_DRIVER_DYNAMIC_DEV.即动态设备管理 if(!(driver-flags&TTY_DRIVER_DYNAMIC_DEV)for(i=0;i num;i+)tty_register_device(driver,i,NULL);proc_tty_register_driver(driver);return 0;这个函数操作比较简单。就是为 tty_driver 创建字符设备。然后将字符设备的操作集指定为 tty_fops.并且将 tty_driver 挂载到 tty_driver
11、s 链表中.其实这个链表的作用跟我们之前分析的 input 子系统中的 input_dev 数组类似。都是以设备号为关键字找到对应的 driver.特别的。如果没有定义 TTY_DRIVER_DYNAMIC_DEV.还会在 sysfs 中创建一个类设备.这样主要是为了 udev 管理设备.以流程图的方式将上述操作表示如下:四:设备文件的操作 设备文件的操作是本节分析的重点。它的主要操作是将各项操作对应到 ldsic 或者是 tty_driver.41:打开 tty 设备的操作 从注册的过程可以看到,所有的操作都会对应到 tty_fops 中。Open 操作对应的操作接口是 tty_open()
12、。代码如下:static int tty_open(struct inode*inode,struct file*filp)struct tty_struct*tty;int noctty,retval;struct tty_driver*driver;int index;dev_t device=inode-i_rdev;unsigned short saved_flags=filp-f_flags;nonseekable_open(inode,filp);retry_open:/O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端 /noctty:需不需要更改当前进程的控制
13、终端 noctty=filp-f_flags&O_NOCTTY;index =-1;retval=0;mutex_lock(&tty_mutex);/设备号(5,0)即/dev/tty.表示当前进程的控制终端 if(device=MKDEV(TTYAUX_MAJOR,0)tty=get_current_tty();/如果当前进程的控制终端不存在,退出 if(!tty)mutex_unlock(&tty_mutex);return-ENXIO;/取得当前进程的 tty_driver driver=tty-driver;index=tty-index;filp-f_flags|=O_NONBLOC
14、K;/*Dont let/dev/tty block*/*noctty=1;*/goto got_driver;#ifdef CONFIG_VT /设备号(4,0).即/dev/tty0:表示当前的控制台 if(device=MKDEV(TTY_MAJOR,0)extern struct tty_driver*console_driver;driver=console_driver;/fg_console:表示当前的控制台 index=fg_console;noctty=1;goto got_driver;#endif /设备号(5,1).即/dev/console.表示外接的控制台.通过 r
15、egesit_console()if(device=MKDEV(TTYAUX_MAJOR,1)driver=console_device(&index);if(driver)/*Dont let/dev/console block*/filp-f_flags|=O_NONBLOCK;noctty=1;goto got_driver;mutex_unlock(&tty_mutex);return-ENODEV;/以文件的设备号为关键字,到 tty_drivers 中搜索所注册的 driver driver=get_tty_driver(device,&index);if(!driver)mute
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 设备 模型 tty 驱动 架构 分析
限制150内