Linux命名空间学习教程(三) PID – Docker.Ren

摘要

[db:摘要]

输入关键字进行搜索搜索:发起问题 发现 话题 帮助 登录注册 命名空间 Linux Linux命名空间学习教程(三) PID 【编者的话】Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid、net、ipc、mnt、uts 等命名空间将容器的进程、网络、消息、文件系统和hostname 隔离开。本文是Linux命名空间系列教程的第三篇,重点介绍PID命名空间。DockerOne在撸代码的基础上进行了校对和整理。继上一篇关于IPC namespace的文章(进程间通信的隔离),我将介绍我个人(作为系统管理员)最喜欢的部分:PID namespaces。如果你尚未阅读过之前的文章,我强烈建议你先阅读一遍这个系列的第一篇文章,了解一下Linux namespace隔离机制。是的,通过这个namespace,我们将有可能重置PID计数,得到自己的“1”进程。这可以被视为在进程标识符(identifier)树中的“chroot”。尤其是当你需要在日常工作中处理pid,并且为4位数(pid)所困时,这将是极为方便的解决方法。要激活PID namespace,只需要把“CLONE_NEWPID”标记添加到“clone”调用。不需要其他额外的步骤。它也能和其他namespace组合使用。一旦激活,子进程getpid()的返回结果将会是不变的“1”。但是,请等一下!这样岂不是有两个“1”进程了?那么进程管理应该怎么办?事实上,这真的真的很像“chroot”。也就是说,它是视角的改变。Host: 所有的进程是可见的,全局的PIDs (init=1, ..., child=xxx, ...)Container: 只有child + descendant(后代)是可见的,本地PIDs (child=1, ...)示例如下:#define_GNU_SOURCE#include<sys/types.h>#include<sys/wait.h>#include<stdio.h>#include<sched.h>#include<signal.h>#include<unistd.h>#defineSTACK_SIZE(1024*1024)//syncprimitiveintcheckpoint[2];staticcharchild_stack[STACK_SIZE];char*constchild_args[]={"/bin/bash",NULL};intchild_main(void*arg){charc;//initsyncprimitiveclose(checkpoint[1]);//wait...read(checkpoint[0],&c,1);printf("-[%5d]World!\n",getpid());sethostname("InNamespace",12);execv(child_args[0],child_args);printf("Ooops\n");return1;}intmain(){//initsyncprimitivepipe(checkpoint);printf("-[%5d]Hello?\n",getpid());intchild_pid=clone(child_main,child_stack+STACK_SIZE,CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID|SIGCHLD,NULL);//furtherinithere(nothingyet)//signal"done"close(checkpoint[1]);waitpid(child_pid,NULL,0);return0;}运行下示例:jean-tiare@jeantiare-Ubuntu:~/blog$gcc-Wallmain-3-pid.c-ons&&sudo./ns-[7823]Hello?-[1]World!root@InNamespace:~/blog#echo"=>MyPID:$$"=>MyPID:1root@InNamespace:~/blog#exit与预期的一样,即使父进程的PID是“7823”,子进程的PID是“1”。如果想试试更好玩的,你可以尝试使用“kill -KILL 7823”,来终止父进程。准确来讲,根本不会发生任何意外情况。jean-tiare@jeantiare-Ubuntu:~/blog$gcc-Wallmain-3-pid.c-ons&&sudo./ns-[7823]Hello?-[1]World!root@InNamespace:~/blog#kill-KILL7823bash:kill:(7823)-Nosuchprocessroot@InNamespace:~/blog#exit隔离如我们预期的一样工作着。并且,如之前所写的那样,这种行为很类似“chroot”,意味着当父进程使用“top”或“ps exf”时,将会显示子进程和它未映射的PID。像“kill”,“cgroups”以及其他机制一样,这是进程控制最基本的特性。等等!说到“top”和“ps exf”,我刚从子进程运行了它们,然后发现和父进程一样的内容。你对我撒谎了!好吧,并不是这样的。这是因为这些工具从真实的“/proc”文件系统获取信息,而它目前尚未被隔离。而这个正是下一篇文章的目标。同时,一个简单的工作区可以是这样的:from childroot@InNamespace:~/blog#mkdir-pprocroot@InNamespace:~/blog#mount-tprocprocprocroot@InNamespace:~/blog#lsproc1dmakey-usersnetsysvipc80drikmsgpagetypeinfotimer_listacpidriverkpagecountpartitionstimer_statsasoundexecdomainskpageflagssched_debugttybuddyinfofblatency_statsschedstatuptimebusfilesystemsloadavgscsiversioncgroupsfslocksselfversion_signaturecmdlineinterruptsmdstatslabinfovmallocinfoconsolesiomemmeminfosoftirqsvmstatcpuinfoioportsmiscstatzoneinfocryptoirqmodulesswapsdeviceskallsymsmountssysdiskstatskcoremtrrsysrq-trigger所以程序似乎再一次变得合理了。如预期一样,你从/bin/bash本身得到了PID “1”,并通过“/bin/ls proc”得到了对应的“80”。是不是比通常的/proc更加nice?这正是我喜欢它的原因。如果你尝试从namespace直接在“/proc”运行这条命令,它在child中可以运行,但是会BREAK你的主namespace。例子如下:jean-tiare@jeantiare-Ubuntu:~/blog$psauxError,dothis:mount-tprocproc/proc这就是PID namespace的全部。有了下一篇文章,我们将能够重新挂载/proc本身,也就可以修复“top”及类似的工具,使之不会破坏parent namespace(父命名空间)。谢谢阅读!原文链接:Introduction to Linux namespaces – Part 3: PID(翻译:孙科 审校:李颖杰)-----------------------------------------Linux命名空间学习教程(一) UTSLinux命名空间学习教程(二) IPCLinux命名空间学习教程(三) PIDLinux命名空间学习教程(四)NS(FS)Linux命名空间学习教程(五)NET

docker

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: