我正在学习Linux的容器技术,并自己编写了一个最小的容器实现。我目前对容器进程的控制台/终端感到困惑,因为我在容器中“重用”控制终端/dev/console
(而不是)。c 5 1
/proc/self/fd/0
我从和确定当前终端/proc/self/fd/2
,读取其设备节点(主要和次要),并使用发现的设备节点在容器中mknod(2)
创建节点。/dev/console
当运行像 PID 1(在 PID 命名空间中)这样的常规应用程序时,这看起来很好/bin/sh
,但在通过 init 系统时则不然(我为此使用了 BusyBox)。
这是我的/etc/inittab
BusyBox rootfs:
::sysinit:/bin/true
::respawn:-/bin/sh
然而,由 init 生成的 shell 总是抱怨can't access tty; job control turned off
。我还尝试使用相同的主机 TTY 节点/dev/tty
(而不是c 5 0
),但此问题仍然存在。
我查看了源代码systemd-nspawn
,发现它创建一个“转发 pty”,其中容器在“转发”到主机端的新 PTY 上运行。该代码对于我的教育项目来说太复杂,因此对我来说不可行。
如何使用容器的主机终端?
详细信息:我的容器程序clone(2)
只有一个带有 flags = 的子项CLONE_NEWGROUP | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD
,该子项设置功能(黑名单)和 seccomp(白名单,系统调用列表取自码头工人),然后pivot_root(2)
再到容器 rootfs 并execve(2)
进入目标应用程序。
我目前正在 Linux 5.3 (Ubuntu 18.04 HWE) 上进行实验,但我预计这在任何最新的 Linux 版本上都不会有所不同。