当前位置: 首页 > news >正文

从pty驱动学习tty设备驱动加载

本文从三个方向研究tty设备
1、tty驱动的加载
2、tty设备的打开
3、tty设备的访问

tty驱动的加载

首先看下tty驱动加载的大体流程
在这里插入图片描述
1、legacy_pty_init
在这里插入图片描述
上述代码是tty_driver结构体比较通用的初始化代码,这里需要注意几点:
一、lines的设置,有可能会生成设置数量的device
二、flag的标置位赋值数据
三、主设备号设置
四、ops回调函数的设置

2、__tty_alloc_driver

/*** __tty_alloc_driver -- allocate tty driver* @lines: count of lines this driver can handle at most* @owner: module which is responsible for this driver* @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags** This should not be called directly, some of the provided macros should be* used instead. Use IS_ERR() and friends on @retval.*/
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,unsigned long flags)
{struct tty_driver *driver;unsigned int cdevs = 1;int err;if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))return ERR_PTR(-EINVAL);driver = kzalloc(sizeof(*driver), GFP_KERNEL);if (!driver)return ERR_PTR(-ENOMEM);kref_init(&driver->kref);driver->num = lines;driver->owner = owner;driver->flags = flags;if (!(flags & TTY_DRIVER_DEVPTS_MEM)) {driver->ttys = kcalloc(lines, sizeof(*driver->ttys),GFP_KERNEL);driver->termios = kcalloc(lines, sizeof(*driver->termios),GFP_KERNEL);if (!driver->ttys || !driver->termios) {err = -ENOMEM;goto err_free_all;}}if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) {driver->ports = kcalloc(lines, sizeof(*driver->ports),GFP_KERNEL);if (!driver->ports) {err = -ENOMEM;goto err_free_all;}cdevs = lines;}driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL);if (!driver->cdevs) {err = -ENOMEM;goto err_free_all;}return driver;
err_free_all:kfree(driver->ports);kfree(driver->ttys);kfree(driver->termios);kfree(driver->cdevs);kfree(driver);return ERR_PTR(err);
}

比较简单明了的代码,主要留意下 tty_driver几个数据成员的赋值

3、tty_set_operations
器件本身回调函数的设置,这个器件与外界通讯的主要途径

static inline void tty_set_operations(struct tty_driver *driver,const struct tty_operations *op)
{driver->ops = op;
}
static const struct tty_operations master_pty_ops_bsd = {.install = pty_install,.open = pty_open,.close = pty_close,.write = pty_write,.write_room = pty_write_room,.flush_buffer = pty_flush_buffer,.unthrottle = pty_unthrottle,.ioctl = pty_bsd_ioctl,.compat_ioctl = pty_bsd_compat_ioctl,.cleanup = pty_cleanup,.resize = pty_resize,.remove = pty_remove
};

4、tty_register_driver

int tty_register_driver(struct tty_driver *driver)
{int error;int i;dev_t dev;struct device *d;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->num, driver->name);}if (error < 0)goto err;if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) {error = tty_cdev_add(driver, dev, 0, driver->num);if (error)goto err_unreg_char;}mutex_lock(&tty_mutex);list_add(&driver->tty_drivers, &tty_drivers);mutex_unlock(&tty_mutex);if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {for (i = 0; i < driver->num; i++) {d = tty_register_device(driver, i, NULL);if (IS_ERR(d)) {error = PTR_ERR(d);goto err_unreg_devs;}}}proc_tty_register_driver(driver);driver->flags |= TTY_DRIVER_INSTALLED;return 0;

在这里插入图片描述
这里的代码,主要是将设备信息保存到全局数组上去,数组大小为255,主设备号%255,获取下标,然后再根据major从小到大的方式,挂到对应下标的链表上去。为后续上层获取设备信息提供支持

tty_cdev_add

static int tty_cdev_add(struct tty_driver *driver, dev_t dev,unsigned int index, unsigned int count)
{int err;/* init here, since reused cdevs cause crashes */driver->cdevs[index] = cdev_alloc();if (!driver->cdevs[index])return -ENOMEM;driver->cdevs[index]->ops = &tty_fops;driver->cdevs[index]->owner = driver->owner;err = cdev_add(driver->cdevs[index], dev, count);if (err)kobject_put(&driver->cdevs[index]->kobj);return err;
}
static const struct file_operations tty_fops = {.llseek		= no_llseek,.read_iter	= tty_read,.write_iter	= tty_write,.splice_read	= generic_file_splice_read,.splice_write	= iter_file_splice_write,.poll		= tty_poll,.unlocked_ioctl	= tty_ioctl,.compat_ioctl	= tty_compat_ioctl,.open		= tty_open,.release	= tty_release,.fasync		= tty_fasync,.show_fdinfo	= tty_show_fdinfo,
};

注册字符设备到系统,这里的tty_fops是中间中转用的
在这里插入图片描述
上面这段代码两点:
1、生成具体的deivce,这里的device会与上面的cdev_add对应起来,对dev/xxx的访问提供支持.这里需要特别说明的是,tty设备没有自己的总线,所有不会有devic和driver匹配的过程。
2、注册proc节点,以供上层访问
到这里tty驱动注册大体完成,总体看起来比较简单

tty设备的打开

先看流程图
在这里插入图片描述

pty的访问写

在这里插入图片描述
上面的打开和写及其它的一些操作,调用流程比较简单。这里不具体介绍了,可根据序列图自行跟踪代码

http://www.dtcms.com/a/438764.html

相关文章:

  • 车牌号黑名单校验功能实现说明
  • 【第五章:计算机视觉-项目实战之生成对抗网络实战】2.基于SRGAN的图像超分辨率实战-(1)实战1:人脸表情生成实战任务详解
  • 【双指针专题】之快乐数
  • 锦州滨海新区城市建设规划网站建设局是个好单位吗
  • 域名搭建网站域名一般在哪里购买
  • 拦截器Interceptor
  • 运营网站流程ui设计的定义
  • 可以做自己的单机网站网站客户案例的
  • 网络编程中UDP协议的广播和组播通信
  • STM32G474单片机开发入门(一)STM32G474RET6单片机详解
  • W3C 简介
  • 菲律宾宿务Cebu(宿雾)介绍
  • Python中如何实现多级缓存
  • 深入掌握 FluentMigrator:C#.NET 数据库迁移框架详解
  • 快速做网站套餐光谷网站建设哪家好
  • 基本定时器(TIM6、TIM7)的基本介绍
  • 荆州网站建设兼职旅游网站功能简介
  • 有关做美食的网站android源码下载网站
  • Ubuntu中部署docker教程及使用指南(易用版)
  • c++之基础A(系统函数)(第一课)
  • 使用scrollview 时,自动滚动条和视图大于子view时居中显示
  • 如何最小阻力练习软件测试相关的英语口语
  • 专门做视频点评的网站iis 新建网站没有文件夹权限
  • 【完整源码+数据集+部署教程】 小麦病害分割系统: yolov8-seg-dyhead
  • Java 黑马程序员学习笔记(进阶篇16)
  • 自适应网站功能网站开发开发的前景
  • 整套网站设计网络服务费
  • python autocad comtypes+pyautocad二次开发 pywin32连不上高版本cad解决办法
  • Linux——0:安装与配置、命令、gcc
  • 健康管理实训室:创新教学场景,推动健康管理人才实战能力提升