echo "abc" > /dev/console 输出到系统控制台(console=ttyS0,表示系统控制台是串口)
echo "abc" > /dev/tty     和下面的相等
echo "abc" > `tty`        输出到本控制台  (tty命令就是输出本控制台)

在Linux中, tty可分为如下几类:

- 串行端口终端(serial port terminal): 指使用计算机串行端口连接的终端设备, /dev/ttySn
- 伪终端(pseudo terminal): 通常是通过ssh登陆的终端, /dev/pts/*
- 控制终端(controlling terminal): 代表当前tty设备 /dev/tty
- 控制台终端(console):  指计算机的输出设备, 通常是printk信息输出的设备, /dev/ttyn、/dev/console

详细定义如下:

/* tty driver types */
#define TTY_DRIVER_TYPE_SYSTEM         0x0001
#define TTY_DRIVER_TYPE_CONSOLE        0x0002
#define TTY_DRIVER_TYPE_SERIAL         0x0003
#define TTY_DRIVER_TYPE_PTY            0x0004
#define TTY_DRIVER_TYPE_SCC            0x0005
/* scc driver */
#define TTY_DRIVER_TYPE_SYSCONS        0x0006

1.echo abc > /dev/ttyS0

tty_cdev_add 给 tty driver 分配字符设备,设置字符设备的文件操作函数指针指向 tty_fops ,后者的写函数为 tty_write

static int tty_cdev_add(struct tty_driver *driver, dev_t dev,unsigned int index, unsigned int count)
{...driver->cdevs[index]->ops = &tty_fops;...
}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,.show_fdinfo  = tty_show_fdinfo,
};

tty_write 只是做一些检查,保证 line discipline 的写函数需要的组件可用,真正的操作由 do_tty_write 调用 ld->ops->write 完成。

static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{struct tty_struct *tty = file_tty(file);struct tty_ldisc *ld;ssize_t ret;if (tty_paranoia_check(tty, file_inode(file), "tty_write"))return -EIO;// tty->ops->write 在 n_tty_write 中使用if (!tty || !tty->ops->write || tty_io_error(tty))return -EIO;/* Short term debug to catch buggy drivers */// tty->ops->write_room 在 n_tty_write-> process_output_block 中使用if (tty->ops->write_room == NULL)tty_err(tty, "missing write_room method\n");ld = tty_ldisc_ref_wait(tty);if (!ld)return hung_up_tty_write(file, buf, count, ppos);if (!ld->ops->write)ret = -EIO;elseret = do_tty_write(ld->ops->write, tty, file, buf, count);tty_ldisc_deref(ld);return ret;
}

2. echo abc > /dev/tty

根据 tty_init 函数, /dev/tty 的文件操作函数指针和 /dev/ttyS0 相同,因此写 /dev/tty 的操作执行的函数和写 /dev/ttyS0 相同。

3.cho abc > /dev/tty1

/dev/ttyn 设备的文件操作指针也是 tty_fops ,因此向其写入数据时,同样会调用 tty_write 函数。
tty_write 调用 line discipline 的写函数完成输出操作,最终调用 con_write 输出字符串。

4. echo abc > /dev/console

/dev/console 使用的文件操作函数指针为:

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

因此写操作调用的函数为 redirected_tty_write :函数首先获取变量 struct file *redirect ,如果文件指针存在,调用 vfs_write 将 buf 中内容输出到 redirect 文件;否则调用 tty_write 完成输出操作。

ssize_t redirected_tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{struct file *p = NULL;spin_lock(&redirect_lock);if (redirect)p = get_file(redirect);spin_unlock(&redirect_lock);if (p) {ssize_t res;res = vfs_write(p, buf, count, &p->f_pos);fput(p);return res;}return tty_write(file, buf, count, ppos);
}

4.1. 控制台重定向 redirect

redirect 定义在 drivers/tty/tty_io.c 中,修改 direct 的函数只有 tioccons ,用于相应 tty ioctl 的 TIOCCONS 命令。

根据 man tty_ioctl 的输出,这个命令的功能为:

重定向控制台输出,将原本要输出到 /dev/console 或者 /dev/tty0 的内容重定向到给定的终端。如果终端是一个伪终端的主设备,将其发送到从设备。

static struct file *redirect;static int tioccons(struct file *file)
{if (!capable(CAP_SYS_ADMIN))return -EPERM;// 传入的文件指针是 /dev/console 或者 /dev/tty0 ,结束重定向if (file->f_op->write == redirected_tty_write) {struct file *f;spin_lock(&redirect_lock);f = redirect;redirect = NULL;spin_unlock(&redirect_lock);if (f)fput(f);return 0;}spin_lock(&redirect_lock);// 如果已经设置了重定向,返回 EBUSYif (redirect) {spin_unlock(&redirect_lock);return -EBUSY;}// 设置重定向redirect = get_file(file);spin_unlock(&redirect_lock);return 0;
}

Linux TTY基本概念之ttys*、tty*、ttyS*、console理解相关推荐

  1. linux ps top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义

    linux ps top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义 linuxpstop http://javawind.net/p131 VIRT:virt ...

  2. linux中who命令显示的tty、pts和(:0)(:0.0)是什么意思

    基本概念:1. tty(终端设备的统称):tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,后来这东西被键盘 ...

  3. tty文件命令 linux,Linux tty 命令 command not found tty 命令详解 tty 命令未找到 tty 命令安装 - CommandNotFound ⚡️ 坑否...

    显示行号 | 选择喜欢的代码风格 默认 GitHub Dune LakeSide Plateau Vibrant Blue Eighties Tranquil tty 命令显示连接到标准输入的终端的文 ...

  4. Linux驱动——mmc概念与框架(一)

    Linux驱动--mmc概念与框架(一) 备注:   1. Kernel版本:5.4   2. 使用工具:Source Insight 4.0   3. 参考博客: Linux MMC framewo ...

  5. Linux终端的概念

    壳(Shell):Shell 是指"提供给使用者使用界面"的软件(命令解析器).我们在使用Linux时不直接与系统打交道而是通过Shell的中间程序.为什么称之为shell呢,是因 ...

  6. Linux内核模块的概念和基本的编程方法

    Linux内核模块的概念和基本的编程方法 标签: Linux内核模块 2013-06-14 18:29 1864人阅读 评论(0) 收藏 举报 分类: linux内核(34) 版权声明:本文为博主原创 ...

  7. Linux——权限|shell运行原理——外壳程序|Linux权限的概念|对人操作|角色和文件操作|文件类型访问权限|修改权限ugo+-|8进制|修改权限|更改文件的拥有

    目录 shell运行原理--外壳程序 Linux权限的概念 对人操作 角色和文件操作 文件类型

  8. Linux(进程概念详解)

    进程是如今编程领域非常重要的一个概念,进程是比较抽象的,不容易直接理解.因为进程与操作系统息息相关,因此在介绍进程之前,笔者打算先简易讲一下操作系统的工作流程,理解操作系统是如何管理软件和硬件的,然后 ...

  9. Linux多线程---线程概念和线程控制

    线程概念 什么是线程? CPU视角: 与进程的关系: Linux下线程概念 那么CPU能分辨task_struct是进程和线程吗? 理解页表 为何以多级页表实现? 多级页表是如何实现的? 多级页表的优 ...

  10. 【Linux】Shell运行原理及Linux权限的概念

    文章目录 一.Shell运行原理 二.Linux权限的概念 1)Linux中的用户 2)Linux权限管理 1.文件访问者的分类(人) 2.文件的权限(事物属性) ① 文件类型 ② 文件基本权限 ④ ...

最新文章

  1. Class com.googlecode.jsonplugin.JSONWriter ca...
  2. matlab simulink互感,Simulink互感模块用set_param函数不能正确赋值
  3. 4K观影体验需要网络端到端带宽50M-100M,时延RTT<=20ms,丢包率PLR<=3.4*10
  4. Forms身份验证基本原理
  5. 自然场景中交通标志牌检测~文末送书
  6. 编程之美-程序理解和时间分析
  7. VirtualBox启动失败,The VM session was aborted.
  8. pandas如何往mysql追加数据
  9. Java笔记(day12)
  10. 基于Springboot实现仓库管理系统
  11. 计算机上的刷新快捷键,刷新快捷键是
  12. Android 深色模式使用失效
  13. linux找不到无线网卡么,找不到无线网卡解决办法
  14. 图像处理——中值滤波
  15. java开学考试感想及代码
  16. DELL强化版《最终幻想11》认证电脑出炉
  17. Linux内核固定虚拟地址映射
  18. 无法启动此程序,因为计算机中丢失rtl70.bpl怎么修复教程
  19. c++手动去除字符串中的空格和tab
  20. 利用numpy对矩阵进行归一化处理的方法

热门文章

  1. 如何在网页中设置一个定时器计算时间?
  2. linux下iptable的用法
  3. windows下查看错误码与错误信息
  4. CentOS7转发非3306端口到3306端口
  5. U盘启动盘如何重装系统?U盘重装系统教程
  6. R语言数学建模(1):Regression analysis
  7. 用Python分析波士顿的房价,酸爽!!!
  8. 【网络是怎么连接的】—— 1.1 生成 HTTP 请求消息
  9. 微信专属输入法你有了吗?防窃听、护隐私
  10. 关于寻迹小车组装建议