学习笔记 --- LINUX TTY子系统框架分析

来源:互联网 发布:js和java哪个好 编辑:程序博客网 时间:2024/04/29 15:59

入口:tty_init
1 创建tty_cdev字符设备
cdev_init     /*设置字符设备操作函数为tty_fops*/
cdev_add        /* 注册字符设备*/
2 创建console_cdev字符设备(用于终端打印)
cdev_init     /*设置字符设备操作函数为console_fops*/
cdev_add      /* 注册字符设备*/

操作tty就是操作字符设备那样,这里以open为例说明。

打开一个tty设备时,调用tty_fops里的:
open ret = __tty_open(inode, filp);dev_t device = inode->i_rdev; //通过设备节点找到设备号driver = get_tty_driver(device, &index)  //通过设备号,找到驱动与indexlist_for_each_entry(p, &tty_drivers, tty_drivers) {  //遍历链表dev_t base = MKDEV(p->major, p->minor_start);if (device < base || device >= base + p->num)continue;*index = device - base;return tty_driver_kref_get(p);}tty = tty_init_dev(driver, index, 0)  //用driver数据初始化一个新的tty_structtty = alloc_tty_struct();initialize_tty_struct(tty, driver, idx);tty->driver = driver;tty->ops = driver->ops;tty->index = idx;retval = tty_driver_install_tty(driver, tty); //安装tty_structretval = tty->ops->open(tty, filp);   //driver->ops里面的open
上面可以知道:操作tty时,通过设备节点找到设备号,再找到驱动,再调用驱动的抽象操作driver->ops,那么这个驱动怎样注册的?
以uart为例,注册驱动时:
ret = uart_register_driver(&s3c24xx_uart_drv)  //uart_driver转换成tty_driver再注册normal  = alloc_tty_driver(drv->nr);drv->tty_driver = normal;normal->driver_state    = drv; //s3c24xx_uart_drv设置为tty_driver的driver_statetty_set_operations(normal, &uart_ops)   driver->ops = op;  //设置好驱动的操作抽象:driver->opsretval = tty_register_driver(normal)list_add(&driver->tty_drivers, &tty_drivers);  //添加到链表
上面的操作抽象driver->ops里面的接口最终调用normal->driver_state的操作函数,而normal->driver_state= drv,所以这里调用的s3c24xx_uart_drv;
比如之前说过再open一个tty时,调用的是driver->ops里面的open,这里就是uart_ops里面的uart_open,这个uart_open是怎么找到他对应的硬件操作的?

uart_openstruct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state  /*driver_state就是s3c24xx_uart_drv,在uart_register_driver(&s3c24xx_uart_drv)的时候设置的:normal->driver_state=drv;*/line = tty->indexstate = uart_get(drv, line);  //state = drv->state + line;uart_startupstruct uart_port *uport = state->uart_port;retval = uport->ops->startup(uport); //uart_open的实际硬件操作

0 0
原创粉丝点击