从图14.2可以看出,特定tty设备驱动的主体工作是填充tty_driver结构体中的成员,实现其中的成员函数,tty_driver结构体的定义如代码清单14.1。代码清单14.1 tty_driver结构体1struct tty_driver

2  {

3    int magic;

4    struct cdev cdev; /*对应的字符设备cdev */

5    struct module *owner;   /*这个驱动的模块拥有者*/

6    const char *driver_name;

7    const char *devfs_name;

8    const char *name;   /*设备名*/

9    int name_base; /* offset of printed name */

10   int major; /*主设备号*/

11   int minor_start; /*开始次设备号*/

12   int minor_num; /*设备数量*/

13   int num; /*被分配的设备数量*/

14   short type; /* tty驱动的类型*/

15   short subtype; /* tty驱动的子类型*/

16   struct termios init_termios; /*初始线路设置*/

17   int flags; /* tty驱动标志*/

18   int refcount; /*引用计数(针对可加载的tty驱动)*/

19   struct proc_dir_entry *proc_entry; /* /proc文件系统入口*/

20   struct tty_driver *other; /*仅对PTY驱动有意义*/

21   ...

22   /*接口函数*/

23   int(*open)(struct tty_struct *tty, struct file *filp);

24   void(*close)(struct tty_struct *tty, struct file *filp);

25   int(*write)(struct tty_struct *tty, const unsigned char *buf, int count);

26   void(*put_char)(struct tty_struct *tty, unsigned char ch);

27   void(*flush_chars)(struct tty_struct *tty);

28   int(*write_room)(struct tty_struct *tty);

29   int(*chars_in_buffer)(struct tty_struct *tty);

30   int(*ioctl)(struct tty_struct *tty, struct file *file, unsigned int cmd,

31     unsigned long arg);

32   void(*set_termios)(struct tty_struct *tty, struct termios *old);

33   void(*throttle)(struct tty_struct *tty);

34   void(*unthrottle)(struct tty_struct *tty);

35   void(*stop)(struct tty_struct *tty);

36   void(*start)(struct tty_struct *tty);

37   void(*hangup)(struct tty_struct *tty);

38   void(*break_ctl)(struct tty_struct *tty, int state);

39   void(*flush_buffer)(struct tty_struct *tty);

40   void(*set_ldisc)(struct tty_struct *tty);

41   void(*wait_until_sent)(struct tty_struct *tty, int timeout);

42   void(*send_xchar)(struct tty_struct *tty, char ch);

43   int(*read_proc)(char *page, char **start, off_t off, int count, int *eof,

44     void *data);

45   int(*write_proc)(struct file *file, const char __user *buffer, unsigned long

46     count, void *data);

47   int(*tiocmget)(struct tty_struct *tty, struct file *file);

48   int(*tiocmset)(struct tty_struct *tty, struct file *file, unsigned int set,

49     unsigned int clear);

50

51   struct list_head tty_drivers;

52 };

tty_driver结构体中的magic表示给这个结构体的“幻数”,设为TTY_DRIVER_MAGIC,在 alloc_tty_driver()函数中被初始化。name与driver_name的不同在于后者表示驱动的名字,用在/proc/tty和sysfs中,而前者表示驱动的设备节点名。type与subtype描述tty驱动的类型和子类型,subtype的值依赖于type,type成员的可能值为TTY_DRIVER_TYPE_SYSTEM(由tty子系统内部使用,subtype应当设为SYSTEM_TYPE_TTY、SYSTEM_TYEP_CONSOLE、SYSTEM_TYPE_SYSCONS或SYSTEM_TYPE_SYSPTMX,这个类型不应当被任何常规tty驱动使用)、TTY_DRIVER_TYPE_CONSOLE(仅被控制台驱动使用)、TTY_DRIVER_TYPE_SERIAL(被任何串行类型驱动使用,subtype应当设为SERIAL_TYPE_NORMAL或SERIAL_TYPE_CALLOUT)、TTY_DRIVER_TYPE_PTY(被伪控制台接口pty使用,此时subtype需要被设置为PTY_TYPE_MASTER或PTY_TYPE_SLAVE)。init_termios为初始线路设置,为一个termios结构体,这个成员被用来提供一个线路设置集合。termios用于保存当前的线路设置,这些线路设置控制当前波特率、数据大小、数据流控设置等,这个结构体包含tcflag_t c_iflag(输入模式标志)、tcflag_t c_oflag(输出模式标志)、tcflag_t c_cflag(控制模式标志)、tcflag_t c_lflag(本地模式标志)、cc_t c_line(线路规程类型)、cc_t c_cc[NCCS](一个控制字符数组)等成员。驱动会使用一个标准的数值集初始化这个成员,它拷贝自tty_std_termios变量,tty_std_termos在tty核心中的定义如代码清单14.2。代码清单14.2 tty_std_termios变量1  struct termios tty_std_termios =

2  {

3   .c_iflag = ICRNL | IXON, /*输入模式*/

4   .c_oflag = OPOST | ONLCR, /*输出模式*/

5   .c_cflag = B38400 | CS8 | CREAD | HUPCL, /*控制模式*/

6   .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |

7   ECHOCTL | ECHOKE | IEXTEN,  /*本地模式*/

8   .c_cc = INIT_C_CC  /*控制字符,用来修改终端的特殊字符映射*/

9  };

tty_driver结构体中的major、minor_start、minor_num表示主设备号、次设备号及可能的次设备数,name表示设备名(如ttyS),第23~49行的函数指针实际和tty_operations结构体等同,它们通常需在特定设备tty驱动模块初始化函数中被赋值。put_char()为单字节写函数,当单个字节被写入设备时这个函数被tty核心调用,如果一个tty驱动没有定义这个函数,将使用count参数为1的write()函数。flush_chars()与wait_until_sent()函数都用于刷新数据到硬件。write_room()指示有多少缓冲区空闲,chars_in_buffer()指示缓冲区中包含的数据数。当ioctl(2)在设备节点上被调用时,ioctl()函数将被tty核心调用。当设备的termios设置被改变时,set_termios()函数将被tty核心调用。throttle ()、unthrottle()、stop()和start()为数据抑制函数,这些函数用来帮助控制tty核心的输入缓存。当tty核心的输入缓冲满时,throttle()函数将被调用,tty驱动试图通知设备不应当发送字符给它。当tty核心的输入缓冲已被清空时,unthrottle()函数将被调用暗示设备可以接收数据。stop()和start()函数非常像throttle()和unthrottle()函数,但它们表示tty驱动应当停止发送数据给设备以及恢复发送数据。当tty驱动挂起tty设备时,hangup()函数被调用,在此函数中进行相关的硬件操作。当tty驱动要在RS-232端口上打开或关闭线路的BREAK状态时,break_ctl()线路中断控制函数被调用。如果state状态设为-1,BREAK状态打开,如果状态设为0,BREAK状态关闭。如果这个函数由tty驱动实现,而tty核心将处理TCSBRK、TCSBRKP、TIOCSBRK和TIOCCBRK这些ioctl命令。flush_buffer()函数用于刷新缓冲区并丢弃任何剩下的数据。set_ldisc()函数用于设置线路规程,当tty核心改变tty驱动的线路规程时这个函数被调用,这个函数通常不需要被驱动定义。send_xchar()为X-类型字符发送函数,这个函数用来发送一个高优先级XON或者XOFF字符给tty设备,要被发送的字符在第2个参数ch中指定。read_proc()和write_proc()为/proc读和写函数。tiocmget()函数用于获得tty设备的线路设置,对应的tiocmset()用于设置tty设备的线路设置,参数set和clear包含了要设置或者清除的线路设置。Linux内核提供了一组函数用于操作tty_driver结构体及tty设备,包括:•分配tty驱动struct tty_driver *alloc_tty_driver(int lines);这个函数返回tty_driver指针,其参数为要分配的设备数量,line会被赋值给tty_driver的num成员,例如:xxx_tty_driver = alloc_tty_driver(XXX_TTY_MINORS);

if (!xxx_tty_driver) //分配失败return -ENOMEM;

•注册tty驱动inttty_register_driver(struct tty_driver *driver);注册tty驱动成功时返回0,参数为由alloc_tty_driver ()分配的tty_driver结构体指针,例如:retval = tty_register_driver(xxx_tty_driver);

if (retval) //注册失败{

printk(KERN_ERR "failed to register tiny tty driver");

put_tty_driver(xxx_tty_driver);

return retval;

}

•注销tty驱动inttty_unregister_driver(struct tty_driver *driver);这个函数与tty_register_driver ()对应,tty驱动最终会调用上述函数注销tty_driver。•注册tty设备void tty_register_device(struct tty_driver *driver, unsigned index,

struct device *device);仅有tty_driver是不够的,驱动必须依附于设备,tty_register_device()函数用于注册关联于tty_driver的设备,index为设备的索引(范围是0~driver->num),如:for (i = 0; i < XXX_TTY_MINORS; ++i)

tty_register_device(xxx_tty_driver, i, NULL);

•注销tty设备void tty_unregister_device(struct tty_driver *driver, unsigned index);上述函数与tty_register_device()对应,用于注销tty设备,其使用方法如:for (i = 0; i < XXX_TTY_MINORS; ++i)

tty_unregister_device(xxx_tty_driver, i);

•设置tty驱动操作void tty_set_operations(struct tty_driver *driver, struct tty_operations *op);上述函数会将tty_operations结构体中的函数指针拷贝给tty_driver对应的函数指针,在具体的tty驱动中,通常会定义1个设备特定的tty_operations,tty_operations的定义如代码清单14.3。tty_operations中的成员函数与tty_driver中的同名成员函数意义完全一致,因此,这里不再赘述。代码清单14.3 tty_operations结构体1  struct tty_operations

2  {

3     int  (*open)(struct tty_struct * tty, struct file * filp);

4     void (*close)(struct tty_struct * tty, struct file * filp);

5     int  (*write)(struct tty_struct * tty,

6                   const unsigned char *buf, int count);

7     void (*put_char)(struct tty_struct *tty, unsigned char ch);

8     void (*flush_chars)(struct tty_struct *tty);

9     int  (*write_room)(struct tty_struct *tty);

10    int  (*chars_in_buffer)(struct tty_struct *tty);

11    int  (*ioctl)(struct tty_struct *tty, struct file * file,

12                unsigned int cmd, unsigned long arg);

13    void (*set_termios)(struct tty_struct *tty, struct termios * old);

14    void (*throttle)(struct tty_struct * tty);

15    void (*unthrottle)(struct tty_struct * tty);

16    void (*stop)(struct tty_struct *tty);

17    void (*start)(struct tty_struct *tty);

18    void (*hangup)(struct tty_struct *tty);

19    void (*break_ctl)(struct tty_struct *tty, int state);

20    void (*flush_buffer)(struct tty_struct *tty);

21    void (*set_ldisc)(struct tty_struct *tty);

22    void (*wait_until_sent)(struct tty_struct *tty, int timeout);

23    void (*send_xchar)(struct tty_struct *tty, char ch);

24    int (*read_proc)(char *page, char **start, off_t off,

25                      int count, int *eof, void *data);

26    int (*write_proc)(struct file *file, const char __user *buffer,

27                      unsigned long count, void *data);

28    int (*tiocmget)(struct tty_struct *tty, struct file *file);

29    int (*tiocmset)(struct tty_struct *tty, struct file *file,

30                         unsigned int set, unsigned int clear);

31 };终端设备驱动都围绕tty_driver结构体而展开,一般而言,终端设备驱动应包含如下组成:•终端设备驱动模块加载函数和卸载函数,完成注册和注销tty_driver,初始化和释放终端设备对应的tty_driver结构体成员及硬件资源。•实现tty_operations结构体中的一系列成员函数,主要是实现open()、close()、write()、tiocmget()、tiocmset()等函数。

ttys和tty_ttyS、tty,console和pty相关推荐

  1. ttys和tty_tty和console区别和联系

    tty是一类char设备的通称,它们有相同的特性,比如对^C的处理,驱动使用tty_register_driver注册一个tty. /dev/console是一个虚拟的tty,它映射到真正的tty上, ...

  2. LINUX下的tty,console与串口

    LINUX下的tty,console与串口 转载于:https://www.cnblogs.com/jingzhishen/p/6144880.html

  3. ttyS、tty,console和pty

    http://blog.chinaunix.net/uid-26510579-id-3192387.html 第十四章  Linux终端设备驱动 本章导读 在Linux系统中,终端设备非常重要,没有终 ...

  4. linux下tty, ttyn, pts, pty, ttySn, console理解

    这一下涉及很多概念:终端,伪终端,虚拟终端,控制终端,串行终端,控制台,--.历史原因这些概念有些模糊,我也理不太清楚.就我直观对dev下设备而言来稍微解释下: /dev/tty 控制终端,即当前用户 ...

  5. linux 什么是tty console和tty和串口的关系 如何在linux下查看tty对应哪个串口

    什么是TTY https://blog.csdn.net/goooooooooo/article/details/1302301?ops_request_misc=%257B%2522request% ...

  6. LINUX下的tty,console与串口分析

    1.LINUX下TTY.CONSOLE.串口之间是怎样的层次关系?具体的函数接口是怎样的?串口是如何被调用的? 2.printk函数是把信息发送到控制台上吧?如何让PRINTK把信息通过串口送出?或者 ...

  7. linux 串口 数量限制,linux – 你的Unix的TTY主要数量是多少?

    我目前正在开发一个串口库,它已经使用特殊的框架来获取有关系统上串行端口的信息.虽然串口是Unix中的基本设计 – 作为答案,如this one证明 – 我认为测试文件是否是串口的好方法是测试字符设备的 ...

  8. linux终端设备:tty子系统相关的初始化

    linux类系统相较于windos类系统用"魔幻"也不为过,神奇的控制台终端如ctrl+alt+F1至F6.UI桌面打开终端.远程ssh登录等等,在神奇的命令行协助下总能随时随地完 ...

  9. 一文彻底讲清Linux tty子系统架构及编程实例

    [摘要]本文详细解读了linux系统下的tty子系统的深层次原理和架构,并参考了LDD3中的代码实例讲述了无硬件下实现一个简单的tty设备驱动模块的编写.对了解tty子系统及下部串口驱动模块的学习有较 ...

最新文章

  1. OpenCV+python:ROI与泛洪填充
  2. 第十四课 如何在DAPP应用实现自带钱包转账功能?
  3. 谷歌浏览器中文版_GitHub上最励志的计算机自学教程:8个月,从中年Web前端到亚马逊百万年薪软件工程师 | 中文版...
  4. k8s的pod资源管理与配置使用凭证的harbor仓库
  5. Mac Supervisor 管理进程
  6. 思维导图_教学工具思维导图
  7. Unity3D自定义资源配置文件
  8. C++基础 匿名对象
  9. 总结:python paramiko winrm
  10. 奥园医美将借助奥园集团品牌优势,在中国引入领先医美技术
  11. html中鼠标悬停时间,jQuery悬停鼠标悬停/鼠标时间
  12. 太恐怖了 两天搞定一个项目 Java Web MVC 网络商城教程+源代码
  13. table固定首行首列
  14. win7电脑怎么录屏?免费的录屏软件分享
  15. 电脑装双系统有什么好处和坏处?
  16. 404错误的处理方式及对SEO的影响(更新)
  17. 【架构设计】什么是CAP理论?
  18. 网络篇 谈谈对学习网络的看法
  19. **R语言中的%in% 用法**
  20. 提效80倍!优维CMDB好样的

热门文章

  1. android战力图、雷达图、七星图、蜘蛛网图自定义控件
  2. Hadoop学习笔记3之启动进程脚本分析
  3. 勒索软件一次次破防,我们拿什么“守城”?
  4. 字节跳动测试岗面试记:二面被按地上血虐,所幸Offer已到手...
  5. 深度测试和Z缓存专场
  6. 游戏开发手记:战斗模块设计
  7. 广发卡分期提额的那点东西,真的就这么简单。
  8. 研大考研:2015西综考研专业分析与就业解析
  9. 国家微生物科学数据中心精品公开课---笔记
  10. 天赋奇臻、炭中极品——Coris珂芮丝