V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
miniliuke
V2EX  ›  Linux

Linux 中 Pid 和 Mnt 命名空间重用的问题

  •  
  •   miniliuke · 2018-08-28 09:05:28 +08:00 · 3252 次点击
    这是一个创建于 2274 天前的主题,其中的信息可能已经有所发展或是发生改变。
    1、我运行了一个进程使用了新的六个命名空间,然后把 /proc/进程号 /ns 下面的六个命名空间 Mount (防止进程关闭后这些文件被删)了,然后关闭,进程但是不知道为什么 Mount 没报错,但是 mnt (即 mount namespace )没有被 Mount......
    2、我使用 Mount 上的命名空间新建进程,发现其他命名空间可以,但是使用 Pid 命名空间时,无法创建新进程,估计是因为,Pid 命名空间里没有 Pid 1 了,所以我想问怎么重用 Pid 命名空间(在创建这个空间的进程已经关闭的情况下)
    27 条回复    2018-08-28 20:26:26 +08:00
    miniliuke
        1
    miniliuke  
    OP
       2018-08-28 09:11:11 +08:00
    换句话说怎么能够让一个进程成为 Pid 命名空间的 1 号进程(在所有 Pid 命名空间里的进程都关闭的情况下)?
    miniliuke
        2
    miniliuke  
    OP
       2018-08-28 09:28:22 +08:00
    怎么才能把这个 Pid 命名空间重新运行起来?
    miniliuke
        3
    miniliuke  
    OP
       2018-08-28 09:44:29 +08:00
    难道 pid namespace 的 1 号进程关了就不能用了?
    miniliuke
        4
    miniliuke  
    OP
       2018-08-28 10:02:08 +08:00
    是不是 init 进程结束 pid namespace 就销毁了??????那 docker stop、start 后 pid namespace 不变意味着 docker 不关 init 进程???????
    raysonx
        5
    raysonx  
       2018-08-28 10:44:16 +08:00
    根据文档( man 9 namespaces ),你无法把一个已经存在的进程变成 PID1,只能在 setns 之后用 clone 或者 fork 创建 PID 为 1 的新进程。
    miniliuke
        6
    miniliuke  
    OP
       2018-08-28 11:13:20 +08:00
    @raysonx fork 可以指定进程号吗?
    miniliuke
        7
    miniliuke  
    OP
       2018-08-28 11:17:07 +08:00
    @raysonx 如果只 fork 的话 cannot allocate memory
    miniliuke
        8
    miniliuke  
    OP
       2018-08-28 11:26:29 +08:00
    如果 PID namespace 中的 init 进程被 kill 掉(SIGKILL),内核会给该 init 的所有其它进程发送 SIGKILL。当 init 结束时,PID namespace 也会被释放,但是也有例外,如果 /proc//ns/pid 被 bind mounted 或者其它进程打开,PID namespace 不会被释放,但是不通过 setns 将新的进程加入到该 PID namespace。
    那么问题来了这个 PID namespace 还有救么?
    miniliuke
        9
    miniliuke  
    OP
       2018-08-28 11:42:48 +08:00 via Android
    可以不被销毁不?
    raysonx
        10
    raysonx  
       2018-08-28 11:55:34 +08:00 via Android
    有点乱。大致思路是 你要先用 setns 把当前进程加入到一个 PID namespace,再调用 fork 或者 clone,这样新进程就被加入新的 PID namespace 了。细节性的东西我得回去翻一下文档。
    raysonx
        11
    raysonx  
       2018-08-28 11:58:37 +08:00 via Android
    PID 1 退出通常意味着 PID namespace 被释放了,类似于电脑关机了。
    docker 有一个后台进程( docker daemon )不退出,但是它本身不是 container 里的 PID 1。container 里的 PID 1 是由用户指定的(通过 dockerfile 里的 entrypoint 和 cmd 指令)
    miniliuke
        12
    miniliuke  
    OP
       2018-08-28 12:04:13 +08:00 via Android
    @raysonx 我使用 docker stop 命令发现 container 的进程没了,然后再 docker start 发现 container 的 pid namespace 还是同一个。按理说 pid 1 已经关过了,那 docker 是怎么重用这个 pid namespace 的呢?
    miniliuke
        13
    miniliuke  
    OP
       2018-08-28 12:05:04 +08:00 via Android
    @raysonx 甚至于我关闭 docker 以后重启还是同一个 pid ns,除非我关机
    raysonx
        14
    raysonx  
       2018-08-28 12:07:57 +08:00 via Android
    @miniliuke docker 没有重用 PID namespace,而是重启了一个新的。
    miniliuke
        15
    miniliuke  
    OP
       2018-08-28 12:08:52 +08:00 via Android
    @raysonx 但我自己实现时关闭 pid1 后 pid ns 就不能新建进程但是能 setns,
    miniliuke
        16
    miniliuke  
    OP
       2018-08-28 12:10:13 +08:00 via Android
    @raysonx 但是 pid namespace 是一样的啊,就是 ls -l /proc/1/ns,发现还是同一个 pid ns
    miniliuke
        17
    miniliuke  
    OP
       2018-08-28 12:14:55 +08:00 via Android
    @raysonx 对了,大佬还有我去 mount 命名空间只有 mnt ns 没有 mount 上且没有报错,为什么啊? pid 的问题我能理解但解决不了,mnt 的问题我都不知道为什么......
    raysonx
        18
    raysonx  
       2018-08-28 12:45:46 +08:00
    @miniliuke 那可能只是 inode 号被重用了而已,你多执行几次看看,会发现数字会变化,并不是同一个 PID namespace.
    关于 mount namespace 的问题,我没有看懂,还请重新描述一遍。
    miniliuke
        19
    miniliuke  
    OP
       2018-08-28 13:38:23 +08:00
    @raysonx 就是为将 /proc/进程号 /ns 里面的文件不在进程结束时被销毁,使用 mount 命令挂载到其他文件上,但是只有 mnt 文件没有被挂载上,也不能 setns......
    miniliuke
        20
    miniliuke  
    OP
       2018-08-28 13:43:40 +08:00
    @miniliuke 报错 mount: wrong fs type, bad option, bad superblock on /proc/14422/ns/mnt,
    missing codepage or helper program, or other error

    In some cases useful info is found in syslog - try
    dmesg | tail or so.
    zealot0630
        21
    zealot0630  
       2018-08-28 13:59:20 +08:00
    是的,pid namespace 里面的 init 进程如果退出,这个 namespace 就用不了了。这点和其他 namespace 行为不一样,因为 init 进程在 pid namespace 里面有特殊作用
    miniliuke
        22
    miniliuke  
    OP
       2018-08-28 14:00:33 +08:00
    @zealot0630 那为什么 setns 无法设置 mnt namespace,这又是为什么......
    henglinli
        23
    henglinli  
       2018-08-28 16:51:04 +08:00 via iPhone
    @miniliuke 最近折腾过 flatpak,你试试 unprivileged user namespaces kernel.unprivileged_userns_clone
    miniliuke
        24
    miniliuke  
    OP
       2018-08-28 16:52:13 +08:00
    @raysonx
    @zealot0630 看了 docker 的实现,终于知道为什么加载不了 mnt ns 了,是 golang 的锅......但是 mount --bind /proc/22752/ns/mnt namespace/test/mnt 还是会报错,不知道为什么 mnt 不能被 mount,其他都可以,可能有什么奇奇怪怪的机制吧
    miniliuke
        25
    miniliuke  
    OP
       2018-08-28 16:54:59 +08:00
    @henglinli 发现全是 Golang 的锅,现在只有一个问题了,为什么 mount --bind /proc/22752/ns/mnt namespace/test/mnt 会报错.......报错:mount: wrong fs type, bad option, bad superblock on /proc/22752/ns/mnt,missing codepage or helper program, or other error
    raysonx
        26
    raysonx  
       2018-08-28 17:45:17 +08:00
    @miniliuke 应该是 propagation flag 造成的问题。
    建议你参考一下"man unshare" 给出的示例:
    # mount --bind /root/namespaces /root/namespaces
    # mount --make-private /root/namespaces
    # touch /root/namespaces/mnt
    # unshare --mount=/root/namespaces/mnt

    换句话讲,你的 namespace/test/mnt 文件所属的 mounting point 的 propagation flag 必须是 private.
    miniliuke
        27
    miniliuke  
    OP
       2018-08-28 20:26:26 +08:00 via Android
    @raysonx 的确是这个问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5665 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 01:41 · PVG 09:41 · LAX 17:41 · JFK 20:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.