1、终端设备

    在Linux系统中,终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。tty是Teletype的缩写,Teletype是最早出现的一种终端设备,很像电传打字机,是由Teletype公司生产的。

Linux中包含如下几类终端设备:

   1).串行端口终端(/dev/ttySn)
使用计算机串行端口连接的终端设备。串行端口对应的设备名称是/dev/ttySn。如/dev/ttyS0、/dev/ttyS1等,设备号分别是(4,0)、(4,1)
   2).伪终端(/dev/pty/)
   显示器通常称为控制台终端,若当前进程有控制终端,则/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令“ps-ax”查看进程与哪个控制终端相连,使用命令“tty”查看它具体对应哪个实际终端设备。

    3).控制台终端(/dev/ttyn, /dev/console)

2、Linux内核tty层次结构

              



(1)、tty线程规程

     以特殊的方式格式化从一个用户或者硬件收到的数据,这种格式化常常采用一个协议转换的形式,如PPP、Bluetooth。

(2)、tty设备发送数据流程

    tty核心从一个用户获取将要发送给一个tty设备的数据,tty核心将数据传递给tty线路规程驱动,接着数据被传递到tty驱动,tty驱动将数据转换为可以发送的硬件格式。

(3)、tty设备接收数据流程

   从tty硬件接收到的数据向上交给tty驱动,进入tty线路规程驱动,再进入tty核心,在此被用户获取。尽管tty核心与tty之间的数据传输会经历tty线路规程的转换,但是tty驱动与tty核心之间也可以直接传输数据。



(4)、上图第一部分,因为终端是一种字符设备,所以要按字符设备的要求来注册,并有对应的file_operations结构体,用于对设备进行操作。

注册的方法有两种:

(1)、在drivers/char/Tty_io.c中定义:

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

此结构体在下面初始化函数中被赋值给对应的字符设备tty


可以在注册tty_driver结构体实例时进行,一般用此方法。

/*

 * Called by a tty driver to register itself.
 */
int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
dev_t dev;
void **p = NULL;


if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
if (!p)
return -ENOMEM;
}


if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start,
driver->num, 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, driver->name);
}
if (error < 0) {
kfree(p);
return error;
}


if (p) {
driver->ttys = (struct tty_struct **)p;
driver->termios = (struct ktermios **)(p + driver->num);
} else {
driver->ttys = NULL;
driver->termios = NULL;
}


cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);

if (error) {
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = NULL;
kfree(p);
return error;
}


mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);
mutex_unlock(&tty_mutex);


if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
for (i = 0; i < driver->num; i++)
   tty_register_device(driver, i, NULL);
}
proc_tty_register_driver(driver);
driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
}


Logo

更多推荐