V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
miniliuke
V2EX  ›  Linux

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

  •  
  •   miniliuke · Aug 28, 2018 · 3668 views
    This topic created in 2809 days ago, the information mentioned may be changed or developed.
    1、我运行了一个进程使用了新的六个命名空间,然后把 /proc/进程号 /ns 下面的六个命名空间 Mount (防止进程关闭后这些文件被删)了,然后关闭,进程但是不知道为什么 Mount 没报错,但是 mnt (即 mount namespace )没有被 Mount......
    2、我使用 Mount 上的命名空间新建进程,发现其他命名空间可以,但是使用 Pid 命名空间时,无法创建新进程,估计是因为,Pid 命名空间里没有 Pid 1 了,所以我想问怎么重用 Pid 命名空间(在创建这个空间的进程已经关闭的情况下)
    27 replies    2018-08-28 20:26:26 +08:00
    miniliuke
        1
    miniliuke  
    OP
       Aug 28, 2018
    换句话说怎么能够让一个进程成为 Pid 命名空间的 1 号进程(在所有 Pid 命名空间里的进程都关闭的情况下)?
    miniliuke
        2
    miniliuke  
    OP
       Aug 28, 2018
    怎么才能把这个 Pid 命名空间重新运行起来?
    miniliuke
        3
    miniliuke  
    OP
       Aug 28, 2018
    难道 pid namespace 的 1 号进程关了就不能用了?
    miniliuke
        4
    miniliuke  
    OP
       Aug 28, 2018
    是不是 init 进程结束 pid namespace 就销毁了??????那 docker stop、start 后 pid namespace 不变意味着 docker 不关 init 进程???????
    raysonx
        5
    raysonx  
       Aug 28, 2018
    根据文档( man 9 namespaces ),你无法把一个已经存在的进程变成 PID1,只能在 setns 之后用 clone 或者 fork 创建 PID 为 1 的新进程。
    miniliuke
        6
    miniliuke  
    OP
       Aug 28, 2018
    @raysonx fork 可以指定进程号吗?
    miniliuke
        7
    miniliuke  
    OP
       Aug 28, 2018
    @raysonx 如果只 fork 的话 cannot allocate memory
    miniliuke
        8
    miniliuke  
    OP
       Aug 28, 2018
    如果 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
       Aug 28, 2018 via Android
    可以不被销毁不?
    raysonx
        10
    raysonx  
       Aug 28, 2018 via Android
    有点乱。大致思路是 你要先用 setns 把当前进程加入到一个 PID namespace,再调用 fork 或者 clone,这样新进程就被加入新的 PID namespace 了。细节性的东西我得回去翻一下文档。
    raysonx
        11
    raysonx  
       Aug 28, 2018 via Android
    PID 1 退出通常意味着 PID namespace 被释放了,类似于电脑关机了。
    docker 有一个后台进程( docker daemon )不退出,但是它本身不是 container 里的 PID 1。container 里的 PID 1 是由用户指定的(通过 dockerfile 里的 entrypoint 和 cmd 指令)
    miniliuke
        12
    miniliuke  
    OP
       Aug 28, 2018 via Android
    @raysonx 我使用 docker stop 命令发现 container 的进程没了,然后再 docker start 发现 container 的 pid namespace 还是同一个。按理说 pid 1 已经关过了,那 docker 是怎么重用这个 pid namespace 的呢?
    miniliuke
        13
    miniliuke  
    OP
       Aug 28, 2018 via Android
    @raysonx 甚至于我关闭 docker 以后重启还是同一个 pid ns,除非我关机
    raysonx
        14
    raysonx  
       Aug 28, 2018 via Android
    @miniliuke docker 没有重用 PID namespace,而是重启了一个新的。
    miniliuke
        15
    miniliuke  
    OP
       Aug 28, 2018 via Android
    @raysonx 但我自己实现时关闭 pid1 后 pid ns 就不能新建进程但是能 setns,
    miniliuke
        16
    miniliuke  
    OP
       Aug 28, 2018 via Android
    @raysonx 但是 pid namespace 是一样的啊,就是 ls -l /proc/1/ns,发现还是同一个 pid ns
    miniliuke
        17
    miniliuke  
    OP
       Aug 28, 2018 via Android
    @raysonx 对了,大佬还有我去 mount 命名空间只有 mnt ns 没有 mount 上且没有报错,为什么啊? pid 的问题我能理解但解决不了,mnt 的问题我都不知道为什么......
    raysonx
        18
    raysonx  
       Aug 28, 2018
    @miniliuke 那可能只是 inode 号被重用了而已,你多执行几次看看,会发现数字会变化,并不是同一个 PID namespace.
    关于 mount namespace 的问题,我没有看懂,还请重新描述一遍。
    miniliuke
        19
    miniliuke  
    OP
       Aug 28, 2018
    @raysonx 就是为将 /proc/进程号 /ns 里面的文件不在进程结束时被销毁,使用 mount 命令挂载到其他文件上,但是只有 mnt 文件没有被挂载上,也不能 setns......
    miniliuke
        20
    miniliuke  
    OP
       Aug 28, 2018
    @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  
       Aug 28, 2018
    是的,pid namespace 里面的 init 进程如果退出,这个 namespace 就用不了了。这点和其他 namespace 行为不一样,因为 init 进程在 pid namespace 里面有特殊作用
    miniliuke
        22
    miniliuke  
    OP
       Aug 28, 2018
    @zealot0630 那为什么 setns 无法设置 mnt namespace,这又是为什么......
    henglinli
        23
    henglinli  
       Aug 28, 2018 via iPhone
    @miniliuke 最近折腾过 flatpak,你试试 unprivileged user namespaces kernel.unprivileged_userns_clone
    miniliuke
        24
    miniliuke  
    OP
       Aug 28, 2018
    @raysonx
    @zealot0630 看了 docker 的实现,终于知道为什么加载不了 mnt ns 了,是 golang 的锅......但是 mount --bind /proc/22752/ns/mnt namespace/test/mnt 还是会报错,不知道为什么 mnt 不能被 mount,其他都可以,可能有什么奇奇怪怪的机制吧
    miniliuke
        25
    miniliuke  
    OP
       Aug 28, 2018
    @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  
       Aug 28, 2018
    @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
       Aug 28, 2018 via Android
    @raysonx 的确是这个问题
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1355 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 17:06 · PVG 01:06 · LAX 10:06 · JFK 13:06
    ♥ Do have faith in what you're doing.