linux 字符驱动 tty,打通linux的tty驱动的数据链路
一、首先把tty驱动在linux中的分层结构理清楚:本文引用地址:http://www.eepw.com.cn/article/201610/305940.htm
自上而下分为TTY核心层、TTY线路规程、TTY驱动。
二、TTY核心层与线路规程层分析
用户空间的程序直接对tty核心层进行读写等相关操作,在tty_io.c中:
int__init tty_init(void)
{
cdev_init(tty_cdev,tty_fops);
if(cdev_add(tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, /dev/tty) 0)
panic(Couldn'tregister /dev/tty driver\n);
device_create(tty_class,NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, tty);
………
}
以上的一段初始化代码可以获取以下信息:
注册了一个字符驱动,用户空间操作对应到tty_fops结构体里的函数:
staticconst struct file_operations tty_fops = {
。llseek =no_llseek,
。read =tty_read,
。write =tty_write,
。poll =tty_poll,
。unlocked_ioctl =tty_ioctl,
。compat_ioctl =tty_compat_ioctl,
。open =tty_open,
。release =tty_release,
。fasync =tty_fasync,
};
对于字符设备驱动,我们知道,读写操作一一对应于fops.
tty_open:
static int tty_open(struct inode *inode, struct file *filp)
{
int index;
dev_tdevice = inode->i_rdev;
structtty_driver *driver;
……
driver= get_tty_driver(device, index);
……
tty= tty_init_dev(driver, index, 0);
……
retval= tty_add_file(tty, filp);
……
if(tty->ops->open)
retval= tty->ops->open(tty, filp);
}
get_tty_driver是根据设备号device,通过查找tty_drivers全局链表来查找tty_driver.
tty_init_dev是初始化一个tty结构体:
tty->driver= driver;
tty->ops= driver->ops;
并建立线路规程:
ldops= tty_ldiscs[N_TTY];
ld->ops= ldops;
tty->ldisc= ld;
其实tty_ldiscs[N_TTY]在console_init中确定,该函数在内核启动的时候调用。
tty_register_ldisc(N_TTY,tty_ldisc_N_TTY);
则:tty_ldiscs[N_TTY]=tty_ldisc_N_TTY;
struct tty_ldisc_ops tty_ldisc_N_TTY = {
。magic = TTY_LDISC_MAGIC,
。name = n_tty,
。open = n_tty_open,
。close = n_tty_close,
。flush_buffer = n_tty_flush_buffer,
。chars_in_buffer= n_tty_chars_in_buffer,
。read = n_tty_read,
。write = n_tty_write,
。ioctl = n_tty_ioctl,
。set_termios = n_tty_set_termios,
。poll = n_tty_poll,
。receive_buf = n_tty_receive_buf,
。write_wakeup = n_tty_write_wakeup
};
tty_add_file主要是将tty保存到file的私有变量private_data中。
tty->ops->open的调用,实则上就是应用driver->ops->open.这样,我们就从tty核心层到tty驱动层了。
tty_write:
static ssize_t tty_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
………
ld= tty_ldisc_ref_wait(tty);
if(!ld->ops->write)
ret= -EIO;
else
ret= do_tty_write(ld->ops->write, tty, file, buf, count);
………
}
从以上这个函数里,可以看到tty_write调用路线规程的write函数,所以,我们来看ldisc中的write函数是怎样的。经过一些操作后,最终调用:
tty->ops->flush_chars(tty);
tty->ops->write(tty,b, nr);
显然,这两个函数,都调用了tty_driver操作函数,因为在之前的tty_open函数中有了tty->ops=driver-> ops这样的操作。那么这个tty_driver是怎样的呢,在TTY系统中,tty_driver是需要在驱动层注册的。注册的时候就初始化了ops, 也就是说,接下来的事情要看tty_driver的了。
tty_read:
static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
………
ld= tty_ldisc_ref_wait(tty);
if(ld->ops->read)
i= (ld->ops->read)(tty, file, buf, count);
else
i= -EIO;
……
}
像tty_write的一样,在tty_read里,也调用了线路规程的对应read函数。不同的是,这个read没有调用tty_driver里ops的read,而是这样:
uncopied= copy_from_read_buf(tty, b, nr);
uncopied+= copy_from_read_buf(tty, b, nr);
从函数名来看copy_from_read_buf,就是从read_buf这个缓冲区拷贝数据。实际上是在tty->read_buf的末尾 tty->read_tail中读取数据。那么read_buf中的数据是怎么来的呢?猜想,那肯定是tty_driver干的事了。
tty_ioctl:
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
……
switch(cmd) {
case… …… :
linux 字符驱动 tty,打通linux的tty驱动的数据链路相关推荐
- linux字符驱动头文件路径,Linux 字符设备驱动例子
编写好驱动,通过挂载的方法将驱动程序挂载到内核里面,大致步骤如下: 一: 1>建立以.c为后缀的c语言程序文件 (里面包含了设备名及设备号等) 2>建立Makefile文件(作用是通过m ...
- linux字符界面播放vcd,linux下刻录vcd的方法
linux下刻录vcd的方法 [日期:2006-11-20] 来源: 作者: [字体:大 中 小] 刻录vcd的命令行工具:制作vcd光盘影像:vcdtools,刻录影像到光盘:cdrdao 安装:d ...
- Linux字符界面的cat,Linux命令之cat详解
cat [选项] [文件] 将文件或标准输入组合输出到标准输出 如果没有指定文件,或文件为'-',则从标准输入读取 注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往往看不清显示的内容.因此,一 ...
- 使用NDB调试Linux字符设备
使用NDB调试Linux字符设备 cdev_init 在Linux中字符设备通过cdev结构体来表示,为了观察Linux上面的字符设备的创建过程,就需要在cdev_init处设置断点. 给cdev_i ...
- 打通linux的tty驱动的数据链路,tty驱动
一.首先把tty驱动在linux中的分层结构理清楚: 自上而下分为TTY核心层.TTY线路规程.TTY驱动. 二.TTY核心层与线路规程层分析 用户空间的程序直接对tty核心层进行读写等相关操作,在t ...
- linux tty连wifi,打通linux的tty驱动的数据链路
一.首先把tty驱动在linux中的分层结构理清楚: 自上而下分为TTY核心层.TTY线路规程.TTY驱动. 二.TTY核心层与线路规程层分析 用户空间的程序直接对tty核心层进行读写等相关操作,在t ...
- 浅谈Linux tty体系,理清tty驱动层次与各种概念
虽然Linux内核是由C语言写的,但处处体现面向对象的设计思想,这对很多只会C语言的朋友来说,理解比较困难,尤其是tty体系,涉及很多混乱的概念. 1. 上古时期的tty.terminal和conso ...
- linux tty设备驱动,18.1. 一个小 TTY 驱动
## 18.1. 一个小 TTY 驱动 为解释 tty 核心如何工作, 我们创建一个小 tty 驱动, 可以被加载, 以及写入读出, 并且卸载. 任何一个 tty 驱动的主要数据结构是 struct ...
- linux 串口驱动 4412,⑮tiny4412 Linux驱动开发之tty子系统(UART)驱动程序
本次说一下tty子系统的驱动编程,因为UART相关的寄存器比较多,同时,应用比较广泛,所以本次的驱动程序量也不少,而且只是完成和特定CPU相关的一部分,通用的部分本次都没有涉及到.在写驱动之前,我们先 ...
- ()shi linux字符设备,Linux字符设备驱动基础(三)
Linux字符设备驱动基础(三) 6 创建设备节点 6.1 手动创建设备节点 查看申请的设备名及主设备号: cat /proc/devices # cat /proc/devices Characte ...
最新文章
- 4 . 2 存储系统
- AIDL注意细节 简单Demo
- how is native onClick event passed to application handler
- Hibernate应用程序级可重复读取
- 12月10日习题答案大剖析!小伙伴们再接再厉
- java 标识符命名规则_java语言基础之标识符和命名规则详解
- 刘强东夫妇向英国捐赠大量防疫物资:在英华侨及留学生可免费认领
- 深入探讨运维驱动的可监控性设计
- 三态门三个状态vhdl_人防门施工方案
- Photoshop插件-删除所有亮度通道蒙板-脚本开发-PS插件
- unity Curvy Splines基础操作:创建可视赛道
- MacBook 右键查询英文查词无法翻译成中文
- 业务流程图设计-Visio设计
- linux----创建主分区、扩展分区、在扩展分区上建立逻辑分区。
- assimp批量转模型_IGS模型批量转换成STL模型
- logstash中无法解析nginx日志中的\x09类似字符导致服务停止
- 读取excel文件并使用matplotlib绘图(含柱状图、柱状图加数值的显示和直方图)
- 蓝牙技术|了解蓝牙LE Audio的Auracast广播音频
- 信息系统项目管理师-项目整合管理
- cogs 1487. 麻球繁衍(概率dp)
热门文章
- arm平台下的反汇编pdf_stm32逆向与安全科普,bin文件逆向反汇编
- python编一个答题程序_从0到1使用python开发一个半自动答题小程序的实现
- python中的三种排序方法,使用冒泡对列表排序,使用自带sort方法进行排序
- 转:Git: 对象原理
- 中国网和七牛云达成战略合作,携手打造国际化融媒中心
- OC 计算幂集 - 递归法
- Mysql + keepalived 实现双主热备读写分离
- oracle --union和union all
- 【权值分块】bzoj1588 [HNOI2002]营业额统计
- Daily Scrum 10.23