打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
linux下/dev/tty, /dev/tty0, /dev/console区别
http://blog.chinaunix.net/uid-20727076-id-3062401.html
在我的fedora11系统(linux2.6.31)下,这三个设备的具体情况如下:
[root@localhost dev]# ls -l tty
crw-rw-rw- 1 root tty 5, 0 2012-01-30 17:26 tty
[root@localhost dev]# ls -l tty0
crw--w---- 1 root root 4, 0 2012-01-30 17:26 tty0
[root@localhost dev]# ls -l console
crw------- 1 root root 5, 1 2012-01-30 17:26 console
1./dev/tty表示控制终端
如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令”ps –ax”来查看进程与哪个控制终端相连。对于你登录的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”可以查看它具体对应哪个实际终端设备。
控制终端可以是Xwindows模式下的伪终端(/dev/pts/*),也可以是控制台虚拟终端(/dev/tty*)
if (device == MKDEV(5, 0)) {
tty = get_current_tty();
if (!tty) {
mutex_unlock(&tty_mutex);
return -ENXIO;
}
driver = tty_driver_kref_get(tty->driver);
index = tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
/* FIXME: Should we take a driver reference ? */
tty_kref_put(tty);
goto got_driver;
}
"driver"对应到驱动,“index"对应到具体的设备,我们从中也可以看出/dev/tty有些类似于到实际所使用终端设备的一个链接。
2./dev/tty0则是当前所使用虚拟终端的一个别名
# tty(查看当前TTY)
/dev/tty1
#echo "test tty0" > /dev/tty0
test tty0
内核实现如下:
if (device == MKDEV(4, 0)) {
extern struct tty_driver *console_driver;
driver = tty_driver_kref_get(console_driver);
index = fg_console;
noctty = 1;
goto got_driver;
}
3./dev/console即控制台,是与操作系统交互的设备,系统将一些信息直接输出到控制台上
内核实现如下:
if (device == MKDEV(5, 1)) {
struct tty_driver *console_driver = console_device(&index);//如何通过这一句得到tty_driver结构呢,这个结构是哪里来的?我们稍候会提到
if (console_driver) {
driver = tty_driver_kref_get(console_driver);
if (driver) {
/* Don't let /dev/console block */
filp->f_flags |= O_NONBLOCK;
noctty = 1;
goto got_driver;
}
}
mutex_unlock(&tty_mutex);
return -ENODEV;
}
通过/dev/console如何对应到具体的设备呢?
在8250.c里,有如下代码:
static struct console serial8250_console = {
.name        = "ttyS",
.write        = serial8250_console_write,
.device        = uart_console_device,
.setup        = serial8250_console_setup,
.early_setup    = serial8250_console_early_setup,
.flags        = CON_PRINTBUFFER,
.index        = -1,
.data        = &serial8250_reg,
};
static int __init serial8250_console_init(void)
{
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
serial8250_isa_init_ports();
register_console(&serial8250_console);
return 0;
}
register_console会将serial8250_console添加到console_drivers的尾部。
而console_device函数遍历console_drivers以得到一个有效的console,得到有效的console以后(在这个例子里,当然会得到serial8250_console),然后会调用他的device方法以得到相应的tty_driver结构,serial8250_console结构的device方法为uart_console_device,uart_console_device的内容如下:
struct tty_driver *uart_console_device(struct console *co, int *index)
{
struct uart_driver *p = co->data;
*index = co->index;
return p->tty_driver;
}
serial8250_reg是个uart_driver的结构体,内容如下:
static struct uart_driver serial8250_reg = {
.owner            = THIS_MODULE,
.driver_name        = "serial",
.dev_name        = "ttyS",
.major            = TTY_MAJOR,
.minor            = 64,
.cons            = SERIAL8250_CONSOLE,
};
注册uart_driver 的时候会分配相应的tty_driver结构
这样通过/dev/console和具体的uart驱动联系起来,通过co->index,又和具体的uart设备联系了起来,这样,内核通过/dev/console就可以操作串口,进行内核信息的输出了。
内核使用/dev/console的地方为kernel初始化的时候:
start_kernel->rest_init->kernel_init->init_post
static noinline int init_post(void)
__releases(kernel_lock)
{
...
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);
...
将控制台设置为标准输入,后续的两个sys_dup(0),则复制标准输入为标准输出和标准错误输出。
这是为调用init进程做准备,之后内核将通过kernel_execve()调用init进程,这样,init进程的输入、输出和错误输出就全部重定向到/dev/console对应的uart设备了.
因为用户应用程序全部为init进程的子或孙进程,所以,默认情况下,用户应用程序的输入、输出和错误输出也全部重定向到了/dev/console对应的uart设备了。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux tty driver
linux内核中串口驱动注册过程(tty驱动)[转]
转载_Linux中tty框架与uart框架之间的调用关系剖析
树莓派3 串口使用 raspberry pi 3B+ uart boot overlay(最全树莓派串口使用)
tty驱动程序框架
tty初探
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服