《Linux Device Drivers》第十八章 TTY驱动程序——note

  • 简介

    • tty设备的名称是从过去的电传打字机缩写而来,最初是指连接到Unix系统上的物理或虚拟终端
    • Linux tty驱动程序的核心紧挨在标准字符设备驱动层之下,并提供了一系列的功能,作为接口被终端类型设备使用
    • 有三种类型的tty驱动程序:控制台、串口和pty
    • /proc/tty/drivers
    • 当前注册并存在于内核的tty设备在/sys/class/tty下都有自己的子目录
  • 小型TTY驱动程序
    • <linux/tty_driver.h>
    • struct tty_driver
    • tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);
    • static struct tty_operations serial_ops = {.open=tiny_open, .close=tiny_close, .write=tiny_write, .write_room=tiny_write_room, .set_termios=tiny_set_termios,}
    • tiny_tty_driver->owner=THIS_MODULE;
    • tiny_tty_driver->driver_name=”tiny_tty”;
    • tiny_tty_driver->name=”ttty”;
    • tiny_tty_driver->devfs_name=”tty/ttty%d”;
    • tiny_tty_driver->major=TINY_TTY_MAJOR;
    • tiny_tty_driver->type=TTY_DRIVER_TYPE_SERIAL;
    • tiny_tty_driver->subtype=SERIAL_TYPE_NORMAL;
    • tiny_tty_driver->flags=TTY_DRIVER_REAL_RAW|TTY_DRIVER_NO_DEVFS;
    • tiny_tty_driver->init_termios=tty_std_termios;
    • tiny_tty_driver->init_termios.c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL;
    • tty_set_operaions(tiny_tty_driver, &serial_ops);
    • retval = tty_register_driver(tiny_tty_driver);
    • for (i=0;i<TINY_TTY_MINORS; ++i) tty_unregister_device(tiny_tty_driver, i);
    • tty_unregister_driver(tiny_tty_driver);
    • termios结构
      • 用来提供一系列安全的设置值
      • struct termios
        • tcflag_t c_iflag;
        • tcflag_t c_oflag;
        • tcflag_t c_cflag;
        • tcflag_c c_lflag;
        • cc_t c_line;
  • tty_driver函数指针

    • open和close

      • 当用户使用open打开由驱动程序分配的设备节点时,tty核心将调用open函数
      • 当调用open函数时,tty驱动程序或者将数据保存到传递给它的tty_struct变量中
    • 数据流
      • 当数据要发送给硬件时,用户调用write函数
      • 首先tty核心接收到了该调用,然后内核将数据发送给tty驱动程序的write函数
      • tty驱动程序在中断上下文中时,它不会调用任何可能休眠的函数
      • 当tty子系统本身需要将一些数据传送到tty设备之外时,可以调用write函数
      • 当tty核心想知道由tty驱动程序提供的可用写入缓冲区大小时,就会调用write_room函数
    • 其他缓冲函数
      • flush_chars
      • wait_until_sent
      • flush_buffer
    • 怎么没有read函数
      • 当tty驱动程序接收到数据后,它将负责把从硬件获取的任何数据传递给tty核心,而不使用传统的read函数
      • tty核心将缓冲数据直到接到来自用户的请求
      • 在一个名为tty_flip_buffer的结构中,tty核心缓冲从tty驱动程序接收的数据
      • tty_insert_flip_char
      • tty_flip_buffer_push
  • TTY线路设置
    • set_termios

      • 大部分termios的用户空间函数将会被库转换成对驱动程序节点的ioctl调用
      • 大量的不同tty ioctl调用会被ttyp核心转换成一个对tty驱动程序的set_termios函数调用
      • tty驱动程序必须能够对在termios结构中所有不同的设置进行解码,并对任何需要的改变做出响应
    • tiocmget和tiocmset
      • 在2.4及更早的内核中,使用了大量的tty ioctl调用来获得及设置不同的控制线路参数
      • 这通过常量TIOCMGET、TIOCMBIS、TIOCMBIC和TIOCMSET来完成
      • TIOCMGET用来获得内核的线路设置值,在2.6.版本的内核中,该ioctl调用被tty驱动程序中的tiocmget回调函数所代替
      • 剩下的三个ioctl现在被简化成tty驱动程序中的一个tiocmset回调函数了
      • int (*tiocmget) (struct tty_struct *tty, struct file *file);
      • int (*tiocmset) (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
  • ioctls
    • 当ioctl为一个设备节点被调用时,tty核心将调用tty_driver结构中的ioctl回调函数
    • 常用词tty ioctl的列表
      • TIOCSERGETLSR

        • 获得这个tty设备线路状态寄存器(LSR)的值
      • TIOCGSERIAL
        • 获得串行线路信息
      • TIOCSSERIAL
        • 设置串行线路信息
      • TIOCMIWAIT
        • 等待MSR的变化
      • TIOCGICOUNT
        • 获得中断计数
  • proc和sys对TTY设备的处理
    • tty核心为任何tty驱动程序都提供了非常简单的办法,用来维护在/proc/tty/driver目录中的一个文件
    • 如果驱动程序定义了read_proc或者write_proc函数,将创建该文件,接着任何对该文件的读写将被发送给驱动程序
  • tty_driver结构详解
    • tty_driver结构用来向tty核心注册一个tty驱动程序
    • struct tty_driver
      • struct module *owner;
      • int magic;
        • 幻数
      • const char *driver_name;
        • 在/proc/tty和sysfs中使用,表示驱动程序的名字
      • const char *name;
        • 驱动程序节点的名字
      • int name_base;
        • 为创建设备名字而使用的开始编号
      • short major;
        • 驱动程序的主设备号
      • short minor_start;
        • 驱动程序使用的最小次设备号
      • short num;
        • 可以分配驱动程序次设备号的个数
      • short type;
        • TTY_DRIVER_TYPE_SYSTEM
        • TTY_DRIVER_TYPE_CONSOLE
        • TTY_DRIVER_TYPE_SERIAL
        • TTY_DRIVER_TYPE_PTY
      • short subtype;
        • 描述向tty核心注册的是何种tty驱动程序
      • struct termios init_termios;
        • 当被创建时,含有初始值的termios结构
      • int flags;
        • 驱动程序标志位
      • struct proc_dir_entry *proc_entry;
        • 该驱动程序的/proc入口结构体
      • struct tty_driver *other;
        • 指向tty从属设备驱动程序的指针
      • void *driver_state;
        • tty驱动程序内部的状态
      • struct tty_driver *next;
      • struct tty_driver *prev;
        • 链接变量
  • tty_operations结构详解
    • tty_operations结构中包含所有的回调函数,它们被tty驱动程序设置,并被tty核心调用
    • struct tty_operations
      • int (*open) (struct tty_struct *tty, struct file *filp);
      • int (*close) (struct tty_struct *tty, struct file *filp);
      • int (*write) (struct tty_struct *tty, const unsigned char *buf, int count);
      • void (*put_char) (struct tty_struct *tty, unsigned char ch);
      • void (*flush_chars) (struct tty_struct *tty);
      • void (*wait_until_sent) (struct tty_struct *tty, int timeout);
      • int (*write_room) (struct tty_struct *tty);
      • int (*chars_in_buffer) (struct tty_struct *tty);
      • int (*ioctl) (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
      • void (*set_termios) (struct tty_struct *tty, struct termios *old);
      • void (*throttle) (struct tty_struct *tty);
      • void (*unthrottle) (struct tty_struct *tty);
      • void (*stop) (struct tty_struct *tty);
      • void (*start) (struct tty_struct *tty);
      • void (*hangup) (struct tty_struct *tty);
      • void (*bread_ctl) (struct tty_struct *tty, int state);
      • void (*flush_buffer) (struct tty_struct *tty);
      • void (*set_ldisc) (struct tty_struct *tty);
      • void (*send_xchar) (struct tty_struct *tty, char ch);
      • int (*read_proc) (char *page, char **start, off_t off, int count, int *eof, void *data);
      • int (*write_proc) (struct file *file, const char *buffer, unsigned long count, void *data);
      • int (*tiocmget) (struct tty_struct *tty, struct file *file);
      • int (*tiocset) (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
  • tty_struct结构详解
    • tty核心使用tty_struct保存当前特定tty端口的状态
    • struct tty_struct
      • unsigned long flags;

        • 当前tty设备的状态
        • TTY_THROTTLED
        • TTY_IO_ERROR
        • TTY_OTHER_CLOSED
        • TTY_EXCLUSIVE
        • TTY_DEBUG
        • TTY_DO_WRITE_WAKEUP
        • TTY_PUSH
        • TTY_CLOSING
        • TTY_DONT_FLIP
        • TTY_HW_COOK_OUT
        • TTY_HW_COOK_IN
        • TTY_PTY_LOCK
        • TTY_NO_WRITE_SPLIT
      • struct tty_flip_buffer flip;
        • tty设备的交替缓冲区
      • struct tty_ldisc ldisc;
        • tty设备的线路规程
      • wait_queue_head_t write_wait;
        • 用于tty写函数的wait_queue
      • struct termios *termios;
        • 指向设置tty设备的termios结构指针
      • unsigned char stopped:1;
        • 表示tty设备是否已经停止
      • unsigned char hw_stopped:1
        • 表示tty设备硬件是否已经停止
      • unsigned char low_latency:1
        • 表示tty设备是否是个慢速设备
      • unsigned char closing:1
        • 表示tty设备是否正在关闭端口
      • struct tty_driver driver;
        • 控制tty设备的当前tty_driver结构
      • void *driver_data;
        • tty_driver用来把数据保存在tty驱动程序中的指针
时间: 2024-09-28 16:41:27

《Linux Device Drivers》第十八章 TTY驱动程序——note的相关文章

《Linux Device Drivers》第八章 分配内存——note

本章主要介绍Linux内核的内存管理. kmalloc函数的内幕 不正确所获取的内存空间清零 分配的区域在物理内存中也是连续的 flags參数 <linux/slab.h> <linux/gfp.h> GFP_KERNEL 在空暇内存较少时把当前进程转入休眠以等待一个页面 分配内存的函数必须是可重入的 GFP_ATOMIC 用于在中断处理例程或其它执行于进程上下文之外的代码中分配内存,不会休眠 GFP_USER 用于为用户空间页分配内存.可能会休眠 GFP_HIGHUSER 类似于

linux device drivers - debugging之proc

在书籍"linux device drivers"的第四章,专门介绍驱动开发中的debugging技术. printk只是其中一种技术,这种技术要求printk打印消息,并且会写入到磁盘里的文件中,这会拖慢整个代码的执行速度. 还有其中的debugging技术,并且对代码执行速度的影响比prink小. 其中讲到了,我们可以让驱动程序在proc文件系统里面创建文件,并且将需要的debugging信息写入到这个文件里面. linux内核提供了相应的API,来和proc文件系统交互,例如创建

《Linux Device Drivers》第十四章 Linux 设备模型

简介 2.6内核的设备模型提供一个对系统结构的一般性抽象描述,用以支持多种不同的任务 电源管理和系统关机 与用户空间通信 热插拔设备 设备类型 对象生命周期 kobject.kset和子系统 kobject是组成设备模型的基本结构 对象的引用计数 sysfs表述 数据结构关联 热插拔事件处理 kobject基础知识 <linux/kobject.h> 嵌入的kobject 内核代码很少去创建一个单独的kobject对象,kobject用于控制对大型域相关对象的访问 kobject的初始化 首先

Linux内核分析——第十八章 调试

第十八章    调试 18.1 准备开始 1.在用户级的程序里,bug表现比较直接:在内核中却不清晰. 2.内核级开发的调试工作远比用户级开发艰难的多. 3.准备工作需要的是: (1)一个bug (2)一个藏匿bug的内核版本 (3)相关内核代码的知识和运气 18.2 内核中的bug 1.内核中的bug多种多样. 2.引用空指针会产生一个oops:垃圾数据会导致系统崩溃. 3.定时限制和竞争条件都允许多个线程在内核中同时运行产生的结果. 18.3 通过打印来调试 一.健壮性 1.健壮性——在任何

《Linux Device Drivers》第十二章 PCI驱动程序——note

简介 本章给出一个高层总线架构的综述 讨论重点是用于访问Peripheral Component Interconnect(PCI,外围设备互联)外设的内核函数 PCI总线是内核中得到最好支持的总线 本章主要介绍PCI驱动程序如果寻找其硬件和获得对它的访问 本章也会介绍ISA总线 PCI接口 PCI是一组完整的规范,定义了计算机的各个不同部分之间应该如何交互 PCI规范涵盖了与计算机接口相关的大部分问题 PCI架构被设计为ISA标准的替代品,有三个主要目标 获得在计算机和外设之间传输数据时更好的

《Linux Device Drivers》第十六章 块设备驱动程序——note

简介 一个块设备驱动程序主要通过传输固定大小的随机数据来访问设备 Linux内核视块设备为与字符设备相异的基本设备类型 Linux块设备驱动程序接口使得块设备可以发挥其最大的功效,但是其复杂程序又是编程者必须面对的一个问题 一个数据块指的是固定大小的数据,而大小的值由内核确定 数据块的大小通常是4096个字节,但是可以根据体系结构和所使用的文件系统进行改变 与数据块对应的是扇区,它是由底层硬件决定大小的一个块,内核所处理的设备扇区大小是512字节 如果要使用不同的硬件扇区大小,用户必须对内核的扇

《Linux Device Drivers》 第十七章 网络驱动程序——note

简介 网络接口是第三类标准Linux设备,本章将描述网络接口是如何与内核其余的部分交互的 网络接口必须使用特定的内核数据结构注册自身,以备与外界进行数据线包交换时调用 对网络接口的常用文件操作是没有意义的,因此在它们身上无法体现Unix的"一切都是文件"的思想 网络驱动程序异步自外部世界的数据包 网络设备向内核请求把外部获得的数据包发送给内核 Linux内核中的网络子系统被设计成完全与协议无关 在网络世界中使用术语"octet"指一组8个的数据位,它是能为网络设备和

《Linux Device Drivers》第十五章 内存映射和DMA——note

简单介绍 很多类型的驱动程序编程都须要了解一些虚拟内存子系统怎样工作的知识 当遇到更为复杂.性能要求更为苛刻的子系统时,本章所讨论的内容迟早都要用到 本章的内容分成三个部分 讲述mmap系统调用的实现过程 讲述怎样跨越边界直接訪问用户空间的内存页 讲述了直接内存訪问(DMA)I/O操作,它使得外设具有直接訪问系统内存的能力 Linux的内存管理 地址类型 Linux是一个虚拟内存系统,这意味着用户程序所使用的地址与硬件使用的物理地址是不等同的 有了虚拟内存,在系统中执行的程序能够分配比物理内存很

《Linux Device Drivers》第六章 高级字符驱动程序操作——note

ioctl 支持的操作,例如 简单数据传输 控制动作,例如用户空间发起弹出介质动作 反馈硬件的状态,例如报告错误信息 参数配置,例如改变波特率 执行自破坏 用户空间的ioctl方法原型:int ioctl(int fd, unsigned long cmd, -);每个ioctl命令就是一个独立的系统调用,而且是非公开的 驱动程序的ioctl方法原型:int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, u