文件 /dev/ptmx 和 /dev/pts/ptmx 之间有什么区别?

文件 /dev/ptmx 和 /dev/pts/ptmx 之间有什么区别?

我曾尝试在我的系统上研究这些设备文件的差异,但谷歌的搜索结果对我来说不起作用。

答案1

/dev/ptmx行为类似于 的符号链接(“打开时将在同一目录中查找 [...]“pts”。”)/dev/pts/ptmx,但前者是所有人可读写的,而后者则无人可访问。与符号链接不同,目标权限无关紧要。可以使用 删除并重新创建它mknod。您无法删除/dev/pts/ptmx

/dev# ll ptmx # Show original
crw-rw-rw- 1 root root 5, 2 Jan 31 03:50 ptmx
/dev# rm ptmx # Delete it
/dev# mknod ptmx c 5 2 # Recreate it
/dev# chmod 666 ptmx
/dev# ll ptmx
crw-rw-rw- 1 root root 5, 2 Jan 31 03:52 ptmx
/dev# ll pts/ptmx
c--------- 1 root root 5, 2 Jan 27 16:23 pts/ptmx
/dev# rm pts/ptmx # Can't delete that one
rm: cannot remove 'pts/ptmx': Operation not permitted

设备类型相同,因此应该具有相同的行为,但devpts挂载的文件系统/dev/pts很特殊,不允许删除其 ptmx。

$ stat /dev/ptmx
[...]
Device: 0,5     Inode: 90          Links: 1     Device type: 5,2
[...]
$ stat /dev/pts/ptmx
[...]
Device: 0,24    Inode: 2           Links: 1     Device type: 5,2
[...]

通常重要的部分是Device type: 5,2意思是“PTY 主多路复用”。这标识了 IO 被发送到内核的哪个位置,但显然有特殊的代码可以使这两种情况有所不同。

记住坐骑本身。根据https://www.kernel.org/doc/Documentation/filesystems/devpts.txt

现在,devpts 文件系统的每个挂载都是不同的,使得在一个挂载中分配的 ptys 及其索引与所有其他挂载中的 ptys 及其索引无关。

两者可用的原因在于向前和向后兼容。它们是两种不同类型的挂载点,分别/devdevtmpfs,而/dev/ptsdevpts其他发行版符号链接/dev/ptmx/dev/pts/ptmx并使其/dev/pts/ptmx可世界读写。为了向后兼容,/dev/ptmx不能删除,因为今天的应用程序(您的终端等)使用它。为了向前兼容,我们希望/dev/pts/ptmx允许命名空间和容器化。我可以将另一个devpts文件系统挂载到其他地方,并且 ID 将与 中的 ID 分开/dev/pts。命名空间和拥有单独 ID 的概念构成了 Docker 等容器化技术的基础。您可以启动 Docker 容器并查看mountls -l /dev && ls -l /dev/pts以了解其中的魔力。

以下是一些一般性的探索:

/tmp# mkdir test
/tmp# mount --make-private -t devtmpfs devtmpfs test # private to allow mount --move
/tmp# cd test
/tmp/test# ls ptmx
ptmx
/tmp/test# ls pts
/tmp/test# exec 3<>ptmx # ptmx acts like a broken symlink to pts/ptmx
-bash: ptmx: No such device
/tmp/test# mount -t devpts devpts pts # Now it works
/tmp/test# ls pts
ptmx
/tmp/test# exec 3<>ptmx # Open /dev/ptmx
/tmp/test# ls pts
0  ptmx
/tmp/test# exec 4<>pts/ptmx # Open /dev/pts/ptmx, same effect
/tmp/test# ls pts
0  1  ptmx
/tmp/test# exec 3>&- # Because they act on the same /dev/pts folder
/tmp/test# ls pts
1  ptmx
/tmp/test# exec 4>&-
/tmp/test# ls pts
ptmx
/tmp/test# exec 3<>ptmx # Set up a few examples
/tmp/test# exec 4<>ptmx
/tmp/test# exec 5<>ptmx
/tmp/test# ls pts
0  1  2  ptmx
/tmp/test# mkdir pts.old # If we move the mount, the /dev/ptmx will point to the new /dev/pts
/tmp/test# mount --move pts pts.old
/tmp/test# mount -t devpts devpts pts
/tmp/test# ls pts
ptmx
/tmp/test# ls pts.old
0  1  2  ptmx
/tmp/test# exec 6<>ptmx # Create in new mount
/tmp/test# ls pts/
0  ptmx
/tmp/test# ls pts.old
0  1  2  ptmx
/tmp/test# mount --move pts pts.new # Same thing if we swap the mounts
/tmp/test# mount --move pts.old pts
/tmp/test# mount --move pts.new pts.old
/tmp/test# ls pts
0  1  2  ptmx
/tmp/test# ls pts.old
0  ptmx
/tmp/test# exec 7<>ptmx
/tmp/test# ls pts
0  1  2  3  ptmx
/tmp/test# ls pts.old
0  ptmx
/tmp/test# exec 8<>pts/ptmx # If we access the pts/ptmx, it will use the corresponding namespace
/tmp/test# ls pts
0  1  2  3  4  ptmx
/tmp/test# ls pts.old
0  ptmx
/tmp/test# exec 9<>pts.old/ptmx
/tmp/test# ls pts
0  1  2  3  4  ptmx
/tmp/test# ls pts.old
0  1  ptmx
/tmp/test# cd ..
/tmp# umount -l test
/tmp# mount -t tmpfs tmpfs test
/tmp# cd test
/tmp/test# mknod ptmx c 5 2
/tmp/test# mkdir pts.new
/tmp/test# ln -s pts.new pts # It does not recursively follow symlinks
/tmp/test# mount -t devpts devpts pts.new
/tmp/test# exec 3<>ptmx
-bash: ptmx: No such device
home@daniel-tablet1:~$ unshare -mr # Create a unprivileged namespace where I am a "fake" root
root@daniel-tablet1:~# # Can't do this because every devtmpfs is the same. Docker uses a tmpfs for /dev.
root@daniel-tablet1:~# # If you create a file in /tmp/test, it will show up in /dev
root@daniel-tablet1:~# # But mounts under /tmp/test will NOT show up in /dev even if I didn't add --make-private
root@daniel-tablet1:~# mount -t devtmpfs devtmpfs Downloads # Can't do this because every devtmpfs is the same
mount: /home/home/Downloads: permission denied.
       dmesg(1) may have more information after failed mount system call.
root@daniel-tablet1:~# mount -t devpts devpts Downloads # All users can create a new devpts namespace
root@daniel-tablet1:~# ls Downloads
ptmx
~# cd /dev
/dev# mount -t devpts devpts pts # I can overmount /dev/pts using an unprivileged mount namespace
/dev# ls pts
ptmx
/dev# exec 3<>ptmx
/dev# ls pts
0  ptmx

相关内容