从这个答案到Linux:/dev/console、/dev/tty 和 /dev/tty0 之间的区别
来自 文档:
/dev/tty Current TTY device /dev/console System console /dev/tty0 Current virtual console
过去的美好时光
/dev/console
是系统管理员控制台。 TTY 是连接到服务器的用户串行设备。 Now/dev/console
和/dev/tty0
代表当前显示,通常是相同的。您可以通过添加到console=ttyS0
来覆盖它grub.conf
。之后你/dev/tty0
就是一个监视器并且/dev/console
是/dev/ttyS0
。
经过 ”系统控制台”,/dev/console
看起来像是文本物理终端的设备文件,就像/dev/tty{1..63}
虚拟控制台的设备文件一样。
通过“/dev/console
和/dev/tty0
代表当前显示并且通常是相同的”,/dev/console
在我看来它也可以是虚拟控制台的设备文件。/dev/console
看起来更像/dev/tty0
是/dev/tty{1..63}
(/dev/tty0
是当前活动的虚拟控制台,并且可以是其中的任何一个/dev/tty{1..63}
)。
什么是/dev/console
?它是干什么用的?
Linux 内核与进程的/dev/console
作用相同吗?/dev/tty
(/dev/tty
是进程的进程会话的控制终端,可以是一个pts,/dev/ttyn
其中n
是从1到63,还是更多?)
另一个回复提到:
内核文档指定
/dev/console
编号为 5:1 的字符设备。打开此字符设备将打开“主”控制台,它是控制台列表中的最后一个 tty。
“控制台列表”是否意味着所有console=
的启动选项?
“/dev/console
作为编号为 5:1 的字符设备”是否意味着它/dev/console
是物理文本终端(即系统控制台)的设备文件? (但是,我上面引用的第一个回复说/dev/console
可以相同,/dev/tty0
这不是物理文本终端,而是虚拟控制台)
谢谢。
答案1
/dev/console
存在的主要目的是向用户空间公开内核的控制台。Linux 内核有关设备的文档现在说
控制台设备
/dev/console
是系统消息应发送到的设备,并且应允许在单用户模式下登录。从Linux 2.1.71开始,/dev/console
由内核管理;对于以前的版本,它应该是指向/dev/tty0
特定虚拟控制台(例如/dev/tty1
)或串行端口主(tty*
而非)设备的符号链接cu*
,具体取决于系统的配置。
/dev/console
,具有主要 5 和次要 1 的设备节点,提供对内核认为是其与系统管理员交互的主要方式的任何内容的访问;这可以是连接到系统的物理控制台(虚拟控制台抽象位于顶部,因此它可以使用tty0
或任何ttyN
地方氮介于 1 和 63 之间),或者串行控制台,或者管理程序控制台,甚至盲文设备。请注意,内核本身不使用/dev/console
:设备节点用于用户空间,而不是用于内核;但是,它确实会检查是否/dev/console
存在且可用,并设置init
其标准输入、输出和错误指向/dev/console
。
如此处所述,/dev/console
是具有固定主要和次要的字符设备,因为它是一个单独的设备(如访问内核的一种方式;不是物理设备),不等同于/dev/tty0
或任何其他设备。这有点类似于情况与/dev/tty
这是它自己的设备 (5:0),因为它提供的功能与其他虚拟控制台或终端设备略有不同。
“控制台列表”确实是由console=
启动参数定义的控制台列表(或者默认控制台,如果没有的话)。您可以通过查看以这种方式定义的控制台/proc/consoles
。/dev/console
确实提供访问权限到最后一个:
您可以在内核命令行上指定多个 console= 选项。输出将出现在所有这些上。打开时将使用最后一个设备
/dev/console
。
答案2
“什么是/dev/console
?”答案在之前的回答。当您知道其他两个问题的答案时,也许这个答案会更清楚。
Q1. “代表物理终端本身的设备文件是什么?”
没有这样的设备文件。
Q2。 “有什么/dev/console
用?”
在 Linux 上,/dev/console
用于在启动(和关闭)期间显示消息。正如斯蒂芬·基特的回答所指出的,它也用于“单用户模式”。使用它没有什么其他意义。
Unix 的“过去的美好时光”/dev/console
是一个专用的物理设备。但在 Linux 中情况并非如此。
相关证据
1.“代表物理终端本身的设备文件是什么?”
让我试着这样理解。
/dev/tty{1..63}
和/dev/pts/n
是代表设备本身的设备文件(尽管它们是仿真),与进程或内核无关。/dev/tty0
代表其中的一个/dev/tty{1..63}
当前被某些东西(可能是内核或外壳进程?)。/dev/tty
表示进程会话当前使用的控制终端。/dev/console
代表内核当前使用的终端?代表物理终端本身的设备文件是什么,与内核或进程无关?
底层设备/dev/tty{1..63}
是struct con_driver
。要查看所有可能的驱动程序,请查看https://elixir.bootlin.com/linux/v4.19/ident/do_take_over_console
这些底层设备没有设备文件!
只有一个最小的用户空间界面来管理它们。
$ head /sys/class/vtconsole/*/name
==> /sys/class/vtconsole/vtcon0/name <==
(S) dummy device
==> /sys/class/vtconsole/vtcon1/name <==
(M) frame buffer device
如果你真的想了解更多,这(M)
模块。即虚拟控制台设备不是由可加载内核模块提供的;它是初始内核映像的一部分(又名“内置”)。
其次,bind
每个子目录中的文件/sys/class/vtconsole
似乎告诉您哪个 vtconsole 设备处于活动状态。如果我写入0
活动的,它似乎会切换到虚拟的。 (GUI VT 似乎不受影响,但文本 VT 停止工作)。为虚拟人写入1
不会激活它。任何一种方法都可以切换回真实的方法。如果我正确地阅读了代码,诀窍是它只echo 1 > bind
适用于作为模块构建的控制台驱动程序(?!)。
为了帧缓冲区具体来说,有一些关于绑定不同帧缓冲区设备的更多信息(/dev/fb0
...)绑定到特定虚拟控制台的更多信息https://kernel.org/doc/Documentation/fb/fbcon.txt。这涉及到一个内核选项fbcon:map=
或一个名为 的命令con2fbmap
。
当然,细节可能会因不同的内核版本、体系结构、固件、设备、驱动程序等而异。我从来没有真正使用过上面的任何接口。内核只是让i915
//inteldrmfb
无论你想调用什么,它都会在加载时接管,替换例如vgacon
.
看来我的 EFI 机器从来没有vgacon
。因此,首先它使用一个虚拟控制台,其次在 1.2 秒后它切换到fbcon
,在efifb
.但到目前为止我还不必关心细节是什么;它就是有效的。
$ dmesg | grep -C2 [Cc]onsole
[ 0.230822] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
[ 0.233164] NR_IRQS: 65792, nr_irqs: 728, preallocated irqs: 16
[ 0.233346] Console: colour dummy device 80x25
[ 0.233571] console [tty0] enabled
[ 0.233585] ACPI: Core revision 20180810
[ 0.233838] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 133484882848 ns
--
[ 1.228393] efifb: scrolling: redraw
[ 1.228396] efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0
[ 1.230393] Console: switching to colour frame buffer device 170x48
[ 1.232090] fb0: EFI VGA frame buffer device
[ 1.232110] intel_idle: MWAIT substates: 0x11142120
--
[ 3.595838] checking generic (e0000000 408000) vs hw (e0000000 10000000)
[ 3.595839] fb: switching to inteldrmfb from EFI VGA
[ 3.596577] Console: switching to colour dummy device 80x25
[ 3.596681] [drm] Replacing VGA console driver
[ 3.597159] [drm] ACPI BIOS requests an excessive sleep of 20000 ms, using 1500 ms instead
[ 3.599830] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
--
[ 3.657050] e1000e 0000:00:19.0 eth0: MAC: 11, PHY: 12, PBA No: FFFFFF-0FF
[ 3.657869] e1000e 0000:00:19.0 eno1: renamed from eth0
[ 4.711453] Console: switching to colour frame buffer device 170x48
[ 4.734356] i915 0000:00:02.0: fb0: inteldrmfb frame buffer device
[ 4.778813] Loading iSCSI transport class v2.0-870.
2.“有什么/dev/console
用?”
您可以使用 /dev/console 作为 TTY 设备。例如,对其进行写入将写入特定的底层设备,该设备也将具有自己的字符设备号。
通常 /dev/console 绑定到 /dev/tty0,但有时它可能绑定到不同的设备。
因此,在这种情况下,写入 /dev/console 将写入 /dev/tty0。反过来,写入 /dev/tty0 相当于写入当前处于活动状态的 /dev/ttyN 设备。
但这提出了一个有趣的问题。访问tty0
将访问不同的虚拟控制台,具体取决于当前处于活动状态的虚拟控制台。人们实际使用什么tty0
,同样console
在 Linux 上使用什么?
从技术上讲,您可以从
console
/读取和写入tty0
,例如运行 agetty
以允许登录tty0
。但这仅作为快速破解有用。因为这意味着你无法利用 Linux 的多个虚拟控制台。systemd
查找sysfs
与 /dev/console 设备关联的属性,以检测底层 TTY 设备。当用户通过启动设置内核控制台时,这允许systemd
自动生成getty
并允许登录串行控制台console=ttyS0
。这很方便;它避免了在两个不同的地方配置此控制台的需要。再次,参见man systemd-getty-generator
。然而,systemd
实际上并没有/dev/console
为此开放。在系统引导期间,您甚至可能还没有安装 sysfs。但您希望能够尽快显示错误和进度消息!所以我们绕到第 1) 点。内核启动 PID 1,并将 stdin/stdout/stderr 连接到
/dev/console
.从一开始就建立这个简单的机制真是太好了。在 Linux 容器内,文件 at
/dev/console
可能会被创建为不同的东西,而不是字符设备号5:1
。相反,它可以创建为 PTS 设备文件。那么通过这个/dev/console
文件 登录就有意义了。systemd
容器内将允许登录此类设备;看man systemd-getty-generator
。当您使用该命令运行容器时,将使用此机制
systemd-nspawn
。 (我认为只有当你systemd-nspawn
在 TTY 上运行时,尽管我无法通过搜索手册页来判断)。systemd-nspawn
创建容器/dev/console
作为来自主机的 PTS 设备的绑定安装。这意味着该 PTS 设备在/dev/pts/
容器内不可见。PTS 设备对于特定
devpts
安装而言是本地的。 PTS 设备是正常规则的一个例外,正常规则是通过设备编号来识别设备。 PTS 设备通过其设备编号和安装方式的组合来识别devpts
。您可以将紧急消息写入
console
/tty0
,以写入用户当前的虚拟控制台。这对于紧急用户空间错误消息可能很有用,类似于打印到控制台的紧急内核消息(请参阅 参考资料man dmesg
)。然而,这样做并不常见,至少在系统完成启动后是这样。rsyslog 有本页的一个示例,它将内核消息打印到
/dev/console
;这在 Linux 上毫无意义,因为默认情况下内核已经这样做了。我无法再次找到的一个例子表明,将其用于非内核消息不是一个好主意,因为系统日志消息太多,你会淹没你的控制台,并且它会妨碍太多。systemd-journald 同样具有将所有日志转发到控制台的选项。原则上,这对于在虚拟环境中进行调试可能很有用。不过,为了调试,我们通常会转发到
/dev/kmsg
。这会将它们保存在内核日志缓冲区中,以便您可以使用dmesg
.与内核本身生成的消息一样,这些消息可能会根据当前的内核配置回显到控制台。