没有合适的资源?快使用搜索试试~ 我知道了~
首页Linux 设备模型之终端设备(tty)驱动架构分析
终端设备 在 Linux 系统中,终端是一种字符型设备,它有多种类型,通常使用 tty 来简称各种类型的 终端设备。tty 是 Teletype 的缩写,Teletype 是最早出现的一种终端设备,很像电传打字 机,是由 Teletype 公司生产的。Linux中包含如下几类终端设备: 1.串行端口终端(/dev/ttySn) 串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。 2.伪终端(/dev/pty/) 伪终端(Pseudo Terminal)是成对的逻辑终端设备 3.控制台终端(/dev/ttyn, /dev/console)
资源详情
资源评论
资源推荐

Linux 设备模型之终端设备(tty)驱动架构分析
*****************************************************
本文系本站原创,欢迎转载!
转载请注明出处: http:// flysunny.cublog.cn
这里感谢:晓刚的分析和指点,及网上的所有串口资源
*****************************************************
一 :前言
终端设备
在 Linux 系统中,终端是一种字符型设备,它有多种类型,通常使用 tty 来简称各种类型的
终端设备。tty 是 Teletype 的缩写,Teletype 是最早出现的一种终端设备,很像电传打字
机,是由 Teletype 公司生产的。Linux 中包含如下几类终端设备:
1.串行端口终端(/dev/ttySn)
串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。
2.伪终端(/dev/pty/)
伪终端(Pseudo Terminal)是成对的逻辑终端设备
3.控制台终端(/dev/ttyn, /dev/console)
二:终端设备驱动结构
1.Tty 架构如下所示:
Tty_core: Tty 核心层
Line discipline : 是线路规程的意思(链路层)。正如它的名字一样,它表示的是这条
终端”线程”的输入与输出规范设置.主要用来进行输入/输出数据的预处理
Tty_driver: Tty_driver就是终端对应的驱动了。它将字符转换成终端可以理解的字串.将
其传给终端设备。

tty 设备发送数据的流程为:
tty_core 从一个用户获得将要发送给一个 tty 设备的数据,tty_core 将数据传递给 Line
discipline 处理,接着数据被传递到 tty_driver,tty 驱动将数据转换为可以发送给硬件
的格式
tty 设备接受数据的流程为:
从 tty 硬件接收到得数据向上交给 tty_driver,进入 Line discipline 处理,再进入
tty_core,在这里它被一个用户获取
尽管大多数时候 tty_core 和 tty_driver 之间的数据传输会经历 Line discipline 的转换,
但是 tty_core 和 tty_driver 之间也可以直接传输数据
2.tty 主要源文件关系及数据流向:
图二:tty 主要源文件关系及数据流向
上图显示了与 tty 相关的主要源文件及数据流向。
tty_io.c:tty_io.c 定义了 tty 设备通用的的 file_operation 结构体,并实现了接口
函数 tty_register_driver()用于注册 tty 设备,它会利用 fs/char_dev.c 提供的接口函数
注册字符设备。tty_io.c 也提供了 tty_register_ldisc()接口函数,用于注册线路规程。
xxx_tty.c:与具体设备对应的 tty 驱动(xxx_tty.c)将实现 tty_driver 结构体中的成
员函数。
Ntty.c:ntty.c 文件则实现了 tty_disc 结构体中的成员
特定 tty 设备的主体工作是填充 tty_driver 结构体中的成员,实现其中的成员函数,
tty_driver 结构体的源码(linux/driver/char/tty_driver.h)如下:

struct tty_driver {
int magic; /* magic number for this structure */
struct cdev cdev;
struct module *owner;
const char *driver_name;
const char *devfs_name;
const char *name;
int name_base; /* offset of printed name */
int major; /* major device number */
int minor_start; /* start of minor device number */
int minor_num; /* number of *possible* devices */
int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct termios init_termios; /* Initial termios */
int flags; /* tty driver flags */
int refcount; /* for loadable tty drivers */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
struct tty_driver *other; /* only used for the PTY driver */
/*
* Pointer to the tty data structures
*/
struct tty_struct **ttys;
struct termios **termios;
struct termios **termios_locked;
void *driver_state; /* only used for the PTY driver */
/*
* Interface routines from the upper tty layer to the tty
* driver. Will be replaced with struct tty_operations.
*/
int (*open)(struct tty_struct * tty, struct file * filp);
void (*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);
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 (*break_ctl)(struct tty_struct *tty, int state);
void (*flush_buffer)(struct tty_struct *tty);
void (*set_ldisc)(struct tty_struct *tty);
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
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 __user *buffer,
unsigned long count, void *data);
int (*tiocmget)(struct tty_struct *tty, struct file *file);
int (*tiocmset)(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
struct list_head tty_drivers;
};
三: tty 驱动接口分析
1.分配 tty 驱动
tty driver 的所有操作都包含在 tty_driver 中。内核即供了一个名叫 alloc_tty_driver()
来分配这个 tty_driver。当然我们也可以在自己的驱动中将它定义成一个静态的结构。对
tty_driver 进行一些必要的初始化之后,调用 tty_register_driver()将其注册.
alloc_tty_driver()接口代码(Linux/driver/char/tty_io.c)如下所示:
struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
memset(driver, 0, sizeof(struct tty_driver));
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
}
return driver;
}

这个函数只有一个参数。这个参数的含义为 line 的个数。也即次设备号的个数。注意每个
设备文件都会对应一个 line.
在这个接口里为 tty_driver 分配内存,然后将 driver->magic 与 driver->num 初始化之后
就返回了.其中 driver->magic 为 tty_driver 这个结构体的“幻数”,设为
TTY_DRIVER_MAGIC,在这里被初始化。
2.注册 tty 驱动
在 这 里 , tty_register_driver() 用 来 注 册 一 个 tty_driver, 源 码 如 下
(Linux/driver/char/tty_io.c):
int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
dev_t dev;
void **p = NULL;
if (driver->flags & TTY_DRIVER_INSTALLED)
return 0;
//TTY_DRIVER_DEVPTS_MEM:使用 devpts 进行动态内存映射
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
if (!p)
return -ENOMEM;
memset(p, 0, driver->num * 3 * sizeof(void *));
}
// /如果没有指定 driver->major,注册字符设备号
if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
(char*)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,
(char*)driver->name);
}
剩余36页未读,继续阅读
















安全验证
文档复制为VIP权益,开通VIP直接复制

评论2