Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1811063
  • 博文数量: 272
  • 博客积分: 1272
  • 博客等级: 少尉
  • 技术积分: 1866
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-09 15:51
文章分类

全部博文(272)

文章存档

2016年(16)

2015年(28)

2014年(97)

2013年(59)

2012年(25)

2011年(47)

分类: LINUX

2013-11-15 15:57:17

本文以linux 2.6.27内核为基础,阅读tty core 源码并作注解,自己接触时间不长,希望与爱好者共同分享,错误之处还望指正。

  linux tty core 是建立在字符设备驱动的基础之上,并为tty类型设备(串口、控制台、虚拟终端)提供一个公用的平台。所以任何一个tty设备驱动的注册都是作为一个字符设备驱动而操作的。下面我们看看代码中是如何处理的:


/* 3/2004 jmc: why do these devices exist? */


//tty核心默认在内核中实现的字符型tty设备驱动

static struct cdev tty_cdev, console_cdev;
#ifdef CONFIG_UNIX98_PTYS
static struct cdev ptmx_cdev;
#endif
#ifdef CONFIG_VT
static struct cdev vc0_cdev;
#endif


/*
* Ok, now we can initialize the rest of the tty devices and can count
* on memory allocations, interrupts etc..
*/
static int __init tty_init(void)
{

//在字符设备模型中加入注册tty_cdev驱动并加入/dev/tty这样的设备

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't register /dev/tty driver/n");
device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
         "tty");


//在字符设备模型中加入注册console_cdev驱动并加入/dev/console这样的设备

cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
     register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
  panic("Couldn't register /dev/console driver/n");
device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
         "console");


//在字符设备模型中加入注册ptmx_cdev驱动并加入/dev/ptmx这样的设备

#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
     register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
  panic("Couldn't register /dev/ptmx driver/n");
device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif


//在字符设备模型中加入注册vc0_cdev驱动并加入/dev/tty0这样的设备

#ifdef CONFIG_VT
cdev_init(&vc0_cdev, &console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
     register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
  panic("Couldn't register /dev/tty0 driver/n");
device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");

vty_init(); //这里暂时不做解释
#endif
return 0;
}


//上面是本身加入的,也就是我们系统一般都有的设备,而且这几种设备都是指向其他的设备,在tty_open中我们将看到以后都会指向其

//他具体的设备。对这几种设备大多数人都存在一定的混淆,这里我就自己的理解解释下:

// /dev/console (5,1) 表示系统的控制台

// /dev/tty (5,0) 表示进程的控制终端

// /dev/tty0 (4,0) 表示当前使用的虚拟终端

// 这样的解释也不是很清楚,这得从历史说起,以前计算机还是比较昂贵的时候,一台电脑上一般接有很多键盘与显示器的组合设备用以

//操作计算机这样的组合设备就是所谓的终端,而还存在一种直接和电脑连接键盘和显示器这就是控制台。而现在的应用环境发生了变化,

//一般把能直接显示系统信息的终端称呼为系统控制台,而其他设备则称呼虚拟终端。也就是当前虚拟终端作控制台。




static const 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,
};

#ifdef CONFIG_UNIX98_PTYS
static const struct file_operations ptmx_fops = {
.llseek  = no_llseek,
.read  = tty_read,
.write  = tty_write,
.poll  = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open  = ptmx_open,
.release = tty_release,
.fasync  = tty_fasync,
};
#endif

static const struct file_operations console_fops = {
.llseek  = no_llseek,
.read  = tty_read,
.write  = redirected_tty_write,
.poll  = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open  = tty_open,
.release = tty_release,
.fasync  = tty_fasync,
};

//从上面看几个驱动的操作函数大致相同,只有ptmx_fops的open方法和console_fops的write方法不同其他操作都是相同的所以在其

//他操作上要兼顾各种设备


//下面我们介绍下tty_driver结构和tty_struct 结构。tty_driver表示一个具体的tty设备的驱动程序,而tty_struct 表示tty设备在

//具体的分析中介绍其成员。


struct tty_driver {
int magic;  /* magic number for this structure */
struct kref kref; /* Reference management */
struct cdev cdev;//可见tty设备驱动是一个字符设备设备驱动
struct module *owner;
const char *driver_name;//这里是指驱动程序的名字
const char *name;//tty设备的命名相关
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 ktermios init_termios; /* Initial termios */
int flags;  /* tty driver flags */
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;//驱动操作的具体tty设备
struct ktermios **termios;
struct ktermios **termios_locked;
void *driver_state;

/*
  * Driver methods
  */

const struct tty_operations *ops;
struct list_head tty_drivers; //用于链接tty驱动全局链表
};

阅读(837) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~