linux tty设备号,linux tty设备
/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(¤t->sighand->siglock, flags);
tty = tty_kref_get(current->signal->tty); //这个就是当前调用进程的控制终端
spin_unlock_irqrestore(¤t->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设备相关推荐
- linux静态分配设备号,Linux驱动开发之静态申请设备号
一. 1.头文件 include/linux/fs.h 2.API 静态申请设备号 int register_chrdev_region(dev_t, unsigned, const char *); ...
- linux设备管理之设备号与次设备号
linux设备管理之主设备号与次设备号 - jinzi - 博客园+ 剽窃 过来的. 记录下,以备查. 主设备号和次设备号 一个字符设备或者块设备都有一个主设备号和次设备号.主设备号和次设备号统称为 ...
- linux中的设备名称和设备号,linux中的设备名称和设备号
2.现代Linux设备号命名规则: 现代Linux要管理的设备种类非常丰富,包括硬盘.U盘.打印机等各种设备.我们仍以硬盘为目标来说明设备命名规则.linux将硬盘分为两类:第一类是传统的IDE硬盘, ...
- 设备驱动分类、设备号、字符设备
一.设备驱动分类 设备驱动分为三大类:字符设备.块设备.网络设备 1.字符设备 该设备对数据的处理按照字节流的形式进行的,支持顺序访问(是有时间的概念),也可以支持随机访问 典型的字符设备:串口.键盘 ...
- airtest获取设备号和获取设备宽度、高度、绝对坐标 相对坐标、滑动屏幕
def setup_function():# 连接当前设备# HUAWEI honor 10 分辨率:2280*1080# OPPO R15 分辨率:2280*1080# Vivo x21 分辨率:2 ...
- linux中的住设备号和次设备号
转自:http://linux-tutorial.info/modules.php?name=MContent&pageid=94 做了少许加粗和删减,需要完整版的请看原文. Major an ...
- Linux进程ID号--Linux进程的管理与调度(三)
进程ID概述 进程ID类型 要想了解内核如何来组织和管理进程ID,先要知道进程ID的类型: 内核中进程ID的类型用pid_type来描述,它被定义在include/linux/pid.h中 enum ...
- 查看 android 设备号,获取Android设备的唯一识别码|设备号|序号|UUID
转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50511283 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...
- linux密码叹号,Linux中“!”感叹号用法技巧大全
这篇文章主要给大家介绍了关于Linux中"!"你不知道的惊叹用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习 ...
最新文章
- 企业USB权限控制心得
- html 中embed标签使用
- Ocelot(六)- 架构图
- php写简单接口_php写接口,对比两种写法
- 微软从安卓那里获取的盈利比重WinPhone 7还多
- Oracle安装-------实例化EM 配置文件时出错问题 ( 转 )
- Concis组件库封装——Avatar头像
- 控制工程基础学习笔记-第1章 概述
- Java jdk的下载与安装
- 服务器装系统鼠标键盘不能动,装系统鼠标键盘不能动
- 二维数组传参,用int指针接收
- Home Assistant设备追踪之ping检测和nmap检测
- Fater RCNN 试着加入注意力机制模型
- 关于2D-DCT字典和克罗内克积以及二维字典的separable特性的个人理解
- Windows11输入法第一个候选词不显示。
- MySQL Workbench构建ER图(实体关系图)
- 基于XMPP的IOS聊天客户端程序(IOS端三)
- FFmpeg最常用命令参数详解及应用实例
- 对渗透新人的几点建议
- rbd-mirror 技术内幕
热门文章
- ACM入门指南[转]
- 254. Drop Eggs (扔鸡蛋经典题)
- 英语流利说显示服务器错误,英语口语流利说系列失望(附音频)
- tyjl ii型计算机联锁系统,TYJL-II型计算机联锁系统的组成及维护..pdf
- 1678 GG's Single Day
- 通过cmd设置path环境变量
- (1)摄像机-计算机接口
- html中加滚动条,html中的div添加滚动条
- Angry Birds for Chrome 升级,带来圣诞新关卡和 Mighty Eagle
- Python 邮件发送