/dev/console是什么

如果系统中存在多个tty设备,想象一下,这时内核启动的log应该打印在哪里,这时内核会从tty中选择一个最合适的作为console,当然内核启动参数中也可以明确的去指定那个tty作为内核的console,/dev/console主要是暴露给用户空间使用的,主要用于系统管理员在改终端上登陆用。

/dev/tty又是什么

The file /dev/tty is a character file with major number 5 and minor number 0, usually of mode 0666 and owner.group root.tty. It is a synonym for the controlling terminal of a process, if any.

/dev/tty can represent different controlling terminals, without being a link, because the driver which implements it determines what the calling process’ controlling terminal is, if any.

如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。

下面从内核源码的角度来分析一下具体的实现:

//./drivers/tty/tty_io.c

int __init tty_init(void)

{

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(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");

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");

consdev = device_create_with_groups(tty_class, NULL,

MKDEV(TTYAUX_MAJOR, 1), NULL,

cons_dev_groups, "console");

if (IS_ERR(consdev))

consdev = NULL;

#ifdef CONFIG_VT

vty_init(&console_fops);

#endif

return 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,

};

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,

};

可以看出它们的打开函数都是tty_open,下面详细分析一下tty_open()这个函数的实现:

static int tty_open(struct inode *inode, struct file *filp)

{

dev_t device = inode->i_rdev; //得到设备号

...

tty = tty_open_current_tty(device, filp);

if (!tty)

tty = tty_open_by_driver(device, inode, filp);

...

tty_add_file(tty, filp);

...

}

/**

* tty_open_current_tty - get locked tty of current task

* @device: device number

* @filp: file pointer to tty

* @return: locked tty of the current task iff @device is /dev/tty

*

* Performs a re-open of the current task's controlling tty.

*

* We cannot return driver and index like for the other nodes because

* devpts will not work then. It expects inodes to be from devpts FS.

*/

static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)

{

struct tty_struct *tty;

int retval;

if (device != MKDEV(TTYAUX_MAJOR, 0)) //判断打开的是否是/dev/tty

return NULL;

tty = get_current_tty();

if (!tty)

return ERR_PTR(-ENXIO);

filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */

/* noctty = 1; */

tty_lock(tty);

tty_kref_put(tty); /* safe to drop the kref now */

retval = tty_reopen(tty);

if (retval < 0) {

tty_unlock(tty);

tty = ERR_PTR(retval);

}

return tty;

}

struct tty_struct *get_current_tty(void)

{

struct tty_struct *tty;

unsigned long flags;

spin_lock_irqsave(&current->sighand->siglock, flags);

tty = tty_kref_get(current->signal->tty); //这个就是当前调用进程的控制终端

spin_unlock_irqrestore(&current->sighand->siglock, flags);

return tty;

}

/* Associate a new file with the tty structure */

void tty_add_file(struct tty_struct *tty, struct file *file)

{

struct tty_file_private *priv = file->private_data;

priv->tty = tty; //将关联的tty放在file的私有数据中保存,这样在后面的tty_read中就能调用对应的tty去执行真正的read动作

priv->file = file;

spin_lock(&tty->files_lock);

list_add(&priv->list, &tty->tty_files);

spin_unlock(&tty->files_lock);

}

可以看出/dev/tty打开的就是当前进程的控制终端,所以不同的session通过

echo hello > /dev/tty

总是能在当前控制终端中显示出来

下面来分析/dev/console的打开过程:

static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,

struct file *filp)

{

...

mutex_lock(&tty_mutex);

driver = tty_lookup_driver(device, filp, &index);

if (IS_ERR(driver)) {

mutex_unlock(&tty_mutex);

return ERR_CAST(driver);

}

/* check whether we're reopening an existing tty */

tty = tty_driver_lookup_tty(driver, filp, index);

if (IS_ERR(tty)) {

mutex_unlock(&tty_mutex);

goto out;

}

...

}

static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,

int *index)

{

...

switch (device) {

case MKDEV(TTYAUX_MAJOR, 1): {

struct tty_driver *console_driver = console_device(index);

if (console_driver) {

driver = tty_driver_kref_get(console_driver);

if (driver) {

/* Don't let /dev/console block */

filp->f_flags |= O_NONBLOCK;

break;

}

}

return ERR_PTR(-ENODEV);

}

}

...

}

/*

* Return the console tty driver structure and its associated index

*/

struct tty_driver *console_device(int *index)

{

struct console *c;

struct tty_driver *driver = NULL;

console_lock();

for_each_console(c) {

if (!c->device)

continue;

driver = c->device(c, index);

if (driver)

break;

}

console_unlock();

return driver;

}

这个函数实际就是返回当前console使用的tty对应的驱动

这里只是分析了个大概,重点是为了说明上面的理解,所有中间略去了很多细节,感兴趣的可以对着代码详细分析。

linux tty设备号,linux tty设备相关推荐

  1. linux静态分配设备号,Linux驱动开发之静态申请设备号

    一. 1.头文件 include/linux/fs.h 2.API 静态申请设备号 int register_chrdev_region(dev_t, unsigned, const char *); ...

  2. linux设备管理之设备号与次设备号

    linux设备管理之主设备号与次设备号 - jinzi - 博客园+ 剽窃 过来的.  记录下,以备查. 主设备号和次设备号 一个字符设备或者块设备都有一个主设备号和次设备号.主设备号和次设备号统称为 ...

  3. linux中的设备名称和设备号,linux中的设备名称和设备号

    2.现代Linux设备号命名规则: 现代Linux要管理的设备种类非常丰富,包括硬盘.U盘.打印机等各种设备.我们仍以硬盘为目标来说明设备命名规则.linux将硬盘分为两类:第一类是传统的IDE硬盘, ...

  4. 设备驱动分类、设备号、字符设备

    一.设备驱动分类 设备驱动分为三大类:字符设备.块设备.网络设备 1.字符设备 该设备对数据的处理按照字节流的形式进行的,支持顺序访问(是有时间的概念),也可以支持随机访问 典型的字符设备:串口.键盘 ...

  5. airtest获取设备号和获取设备宽度、高度、绝对坐标 相对坐标、滑动屏幕

    def setup_function():# 连接当前设备# HUAWEI honor 10 分辨率:2280*1080# OPPO R15 分辨率:2280*1080# Vivo x21 分辨率:2 ...

  6. linux中的住设备号和次设备号

    转自:http://linux-tutorial.info/modules.php?name=MContent&pageid=94 做了少许加粗和删减,需要完整版的请看原文. Major an ...

  7. Linux进程ID号--Linux进程的管理与调度(三)

    进程ID概述 进程ID类型 要想了解内核如何来组织和管理进程ID,先要知道进程ID的类型: 内核中进程ID的类型用pid_type来描述,它被定义在include/linux/pid.h中 enum ...

  8. 查看 android 设备号,获取Android设备的唯一识别码|设备号|序号|UUID

    转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50511283 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...

  9. linux密码叹号,Linux中“!”感叹号用法技巧大全

    这篇文章主要给大家介绍了关于Linux中"!"你不知道的惊叹用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习 ...

最新文章

  1. 企业USB权限控制心得
  2. html 中embed标签使用
  3. Ocelot(六)- 架构图
  4. php写简单接口_php写接口,对比两种写法
  5. 微软从安卓那里获取的盈利比重WinPhone 7还多
  6. Oracle安装-------实例化EM 配置文件时出错问题 ( 转 )
  7. Concis组件库封装——Avatar头像
  8. 控制工程基础学习笔记-第1章 概述
  9. Java jdk的下载与安装
  10. 服务器装系统鼠标键盘不能动,装系统鼠标键盘不能动
  11. 二维数组传参,用int指针接收
  12. Home Assistant设备追踪之ping检测和nmap检测
  13. Fater RCNN 试着加入注意力机制模型
  14. 关于2D-DCT字典和克罗内克积以及二维字典的separable特性的个人理解
  15. Windows11输入法第一个候选词不显示。
  16. MySQL Workbench构建ER图(实体关系图)
  17. 基于XMPP的IOS聊天客户端程序(IOS端三)
  18. FFmpeg最常用命令参数详解及应用实例
  19. 对渗透新人的几点建议
  20. rbd-mirror 技术内幕

热门文章

  1. ACM入门指南[转]
  2. 254. Drop Eggs (扔鸡蛋经典题)
  3. 英语流利说显示服务器错误,英语口语流利说系列失望(附音频)
  4. tyjl ii型计算机联锁系统,TYJL-II型计算机联锁系统的组成及维护..pdf
  5. 1678 GG's Single Day
  6. 通过cmd设置path环境变量
  7. (1)摄像机-计算机接口
  8. html中加滚动条,html中的div添加滚动条
  9. Angry Birds for Chrome 升级,带来圣诞新关卡和 Mighty Eagle
  10. Python 邮件发送