Chinaunix首页 | 论坛 | 博客
  • 博客访问: 729362
  • 博文数量: 134
  • 博客积分: 3207
  • 博客等级: 中校
  • 技术积分: 1995
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-01 20:47
文章分类

全部博文(134)

文章存档

2022年(1)

2020年(7)

2018年(2)

2016年(5)

2015年(14)

2014年(21)

2013年(3)

2012年(1)

2011年(15)

2010年(30)

2009年(35)

分类: 嵌入式

2010-07-26 16:59:02

在Linux系统中,终端是一种字符设备,它有多种类型,通常使用tty来简称各种类型的终端设备。tty是Teletype的缩写,Teletype是最早出现的一种终端设备,很像电传打字机,是由Teletype公司产生的。Linux系统包含以下几类终端设备:
1、串行终端设备(/dev/ttySn).它是使用计算机串行端口连接的终端设备,也就是我们主板上的串口。
2、伪终端(/dev/pty/).它是成对的逻辑终端设备,并存在成对的设备文件。如/dev/pty3和/dev/ttyp3,它们和实际的物理设备并不直接相关。
3、控制台终端(/dev/ttyn, /dev/console).如果当前进程有控制终端,那么/dev/tty就是当前进程的控制终端的设备特殊文件。
通过查看/proc/tty/drivers文件可以获知什么类型的tty设备文件存在以及什么驱动被加载到内核。这个文件包括一个当前存在的不同tty驱动的列表,包括驱动名、默认的节点名、驱动的主编号、这个驱动使用的次编号范围以及tty驱动的类型。看下面一个例子:
$ cat /proc/tty/drivers 
/dev/tty             /dev/tty        5       0 system:/dev/tty
/dev/console         /dev/console    5       1 system:console
/dev/ptmx            /dev/ptmx       5       2 system
/dev/vc/0            /dev/vc/0       4       0 system:vtmaster
rfcomm               /dev/rfcomm   216 0-255 serial
serial               /dev/ttyS       4 64-111 serial
pty_slave            /dev/pts      136 0-1048575 pty:slave
pty_master           /dev/ptm      128 0-1048575 pty:master
unknown              /dev/tty        4 1-63 console

学习tty设备驱动,我们要先会加载和卸载此设备。
tty设备驱动有一个很重要的结构体:tty_driver。它用来注册和注销一个 tty 驱动到 tty 内核。
linux2.6.28/include/linux/tty_driver.h:
struct tty_driver {
 272        int     magic;          /* magic number for this structure */
 273        struct kref kref;       /* Reference management */
 274        struct cdev cdev;
 275        struct module   *owner;
 276        const char      *driver_name;
 277        const char      *name;
 278        int     name_base;      /* offset of printed name */
 279        int     major;          /* major device number */
 280        int     minor_start;    /* start of minor device number */
 281        int     minor_num;      /* number of *possible* devices */
 282        int     num;            /* number of devices allocated */
 283        short   type;           /* type of tty driver */
 284        short   subtype;        /* subtype of tty driver */
 285        struct ktermios init_termios; /* Initial termios */
 286        int     flags;          /* tty driver flags */
 287        struct proc_dir_entry *proc_entry; /* /proc fs entry */
 288        struct tty_driver *other; /* only used for the PTY driver */
 289
 290        /*
 291         * Pointer to the tty data structures
 292         */
 293        struct tty_struct **ttys;
 294        struct ktermios **termios;
 295        struct ktermios **termios_locked;
 296        void *driver_state;
 297
 298        /*
 299         * Driver methods
 300         */
 301
 302        const struct tty_operations *ops;
 303        struct list_head tty_drivers;
 304};

308  extern struct tty_driver *alloc_tty_driver(int lines);
这个函数返回tty_driver指针,其参数为要分配的设备数量,line会被赋值给tty_driver的num成员.
为创建一个 struct tty_driver, 函数 alloc_tty_driver 必须用这个驱动作为参数而支持的 tty 设备号来调用.

以下函数用来注册tty设备和驱动:
linux2.6.28/include/linux/tty.h:
 343 extern int tty_register_driver(struct tty_driver *driver); 注册tty驱动
 344 extern int tty_unregister_driver(struct tty_driver *driver); 注销tty驱动
 345 extern struct device *tty_register_device(struct tty_driver *driver,
 346                                          unsigned index, struct device *dev); 注册tty设备
 347 extern void tty_unregister_device(struct tty_driver *driver, unsigned index); 注销tty设备

下面一个例子来加载和卸载tty模块:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/tty.h>    /*注意:tty.h和tty_driver.h顺序不能颠倒,必须是tty.h在tty_driver.h前面。一旦顺序颠倒,就会提示有错误。*/

#include <linux/tty_driver.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/serial_reg.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lan");

#define TTY_LAN_MINORS_NUM    5
#define TTY_LAN_MAJOR        202
static struct tty_driver *tty_lan_driver;

static int tty_lan_open(struct tty_struct *tty, struct file *filp);
static struct tty_operations tty_lan_ops = {
    .open = tty_lan_open,
};

static int __init tty_lan_init(void)
{
    int i;
    int retval;
    
    tty_lan_driver = alloc_tty_driver(TTY_LAN_MINORS_NUM);
    if(!tty_lan_driver)
        return -ENOMEM;
    
    tty_lan_driver->owner = THIS_MODULE;
    tty_lan_driver->driver_name = "tty_lan";
    tty_lan_driver->name = "ttty_lan";
    tty_lan_driver->major = TTY_LAN_MAJOR,
    tty_lan_driver->minor_start = 0;    
    tty_lan_driver->type = TTY_DRIVER_TYPE_SERIAL;
    tty_lan_driver->subtype = SERIAL_TYPE_NORMAL;
    tty_lan_driver->flags = TTY_DRIVER_REAL_RAW;
    tty_lan_driver->init_termios = tty_std_termios;
    tty_lan_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  
    retval = tty_register_driver(tty_lan_driver);
    if(retval){
        printk(KERN_ERR"Failed to register tty_lan_driver!\n");
        put_tty_driver(tty_lan_driver);
        return retval;
    }

    for(i = 0; i < TTY_LAN_MINORS_NUM; i++)
        tty_register_device(tty_lan_driver, i, NULL);
    return 0;
}

static int tty_lan_open(struct tty_struct *tty, struct file *filp)
{
    return 0;
}

static void __exit tty_lan_exit(void)
{
    int i;
    for(i = 0; i < TTY_LAN_MINORS_NUM; i++)
        tty_unregister_device(tty_lan_driver, i);
    tty_unregister_driver(tty_lan_driver);
}

module_init(tty_lan_init);
module_exit(tty_lan_exit);






Makefile:

UNAME = $(shell uname -r)
LINUX_PATH = /lib/modules/$(UNAME)/build
obj-m = tty_lan.o
all:
    $(MAKE) -C $(LINUX_PATH) M=$(PWD) modules
clean:    
    $(MAKE) -C $(LINUX_PATH) M=$(PWD) clean


我们编译并加载此模块后,观察如下文件:
$ cat /proc/tty/drivers 
/dev/tty             /dev/tty        5       0 system:/dev/tty
/dev/console         /dev/console    5       1 system:console
/dev/ptmx            /dev/ptmx       5       2 system
/dev/vc/0            /dev/vc/0       4       0 system:vtmaster
tty_lan              /dev/ttty_lan 202 0-4 serial
rfcomm               /dev/rfcomm   216 0-255 serial
serial               /dev/ttyS       4 64-111 serial
pty_slave            /dev/pts      136 0-1048575 pty:slave
pty_master           /dev/ptm      128 0-1048575 pty:master
unknown              /dev/tty        4 1-63 console
红色字体那一行就是我的tty设备。

我创建了5个设备。到/dev目录下看看吧:
$ ls -l /dev/ttty_lan*
crw-rw---- 1 root root 202, 0 2010-07-26 16:40 /dev/ttty_lan0
crw-rw---- 1 root root 202, 1 2010-07-26 16:40 /dev/ttty_lan1
crw-rw---- 1 root root 202, 2 2010-07-26 16:40 /dev/ttty_lan2
crw-rw---- 1 root root 202, 3 2010-07-26 16:40 /dev/ttty_lan3
crw-rw---- 1 root root 202, 4 2010-07-26 16:40 /dev/ttty_lan4

OK,tty设备的创建已经完成。后面就要对tty设备文件进行操作了。
阅读(3448) | 评论(1) | 转发(2) |
给主人留下些什么吧!~~

jonahsyh2014-12-28 21:46:56

[   75.820095]  [<c03b83a2>] ? tty_register_driver+0xf2/0x1c0
[   75.820111]  [<c03b8761>] ? alloc_tty_driver+0x51/0x70
[   75.820311]  [<d085307b>] ? tty_lan_init+0x7b/0xb7 [tty_lan]
[   75.820329]  [<c0101131>] ? do_one_initcall+0x31/0x190
[   75.820334]  [<d0853000>] ? tty_lan_init+0x0/0xb7 [tty_lan]
[   75.820340]  [<c01833c0&