Linux命名空间学习教程(三) PID

本文讲的是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>
#define STACK_SIZE (1024 * 1024)
// sync primitive
int checkpoint[2];
static char child_stack[STACK_SIZE];
char* const child_args[] = {
"/bin/bash",
NULL
};
int child_main(void* arg) {
char c;
// init sync primitive
close(checkpoint[1]);
// wait...
read(checkpoint[0], &c, 1);
printf(" - [%5d] World !\n", getpid());
sethostname("In Namespace", 12);
execv(child_args[0], child_args);
printf("Ooops\n");
return 1;
}
int main() {
// init sync primitive
pipe(checkpoint);
printf(" - [%5d] Hello ?\n", getpid());
int child_pid = clone(child_main, child_stack+STACK_SIZE,
  CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | SIGCHLD, NULL);
// further init here (nothing yet)
// signal "done"
close(checkpoint[1]);
waitpid(child_pid, NULL, 0);
return 0;
}

运行下示例:

jean-tiare@jeantiare-Ubuntu:~/blog$ gcc -Wall main-3-pid.c -o ns && sudo ./ns
- [ 7823] Hello ?
- [    1] World !
root@In Namespace:~/blog# echo "=> My PID: $$"
=> My PID: 1
root@In Namespace:~/blog# exit

与预期的一样,即使父进程的PID是“7823”,子进程的PID是“1”。如果想试试更好玩的,你可以尝试使用“kill -KILL 7823”,来终止父进程。准确来讲,根本不会发生任何意外情况。

jean-tiare@jeantiare-Ubuntu:~/blog$ gcc -Wall main-3-pid.c -o ns && sudo ./ns
- [ 7823] Hello ?
- [    1] World !
root@In Namespace:~/blog# kill -KILL 7823
bash: kill: (7823) - No such process
root@In Namespace:~/blog# exit

隔离如我们预期的一样工作着。并且,如之前所写的那样,这种行为很类似“chroot”,意味着当父进程使用“top”或“ps exf”时,将会显示子进程和它未映射的PID。像“kill”,“cgroups”以及其他机制一样,这是进程控制最基本的特性。

等等!说到“top”和“ps exf”,我刚从子进程运行了它们,然后发现和父进程一样的内容。你对我撒谎了!

好吧,并不是这样的。这是因为这些工具从真实的“/proc”文件系统获取信息,而它目前尚未被隔离。而这个正是下一篇文章的目标。

同时,一个简单的工作区可以是这样的:


from child

root@In Namespace:~/blog# mkdir -p proc
root@In Namespace:~/blog# mount -t proc proc proc
root@In Namespace:~/blog# ls proc
1          dma          key-users      net            sysvipc
80         dri          kmsg           pagetypeinfo   timer_list
acpi       driver       kpagecount     partitions     timer_stats
asound     execdomains  kpageflags     sched_debug    tty
buddyinfo  fb           latency_stats  schedstat      uptime
bus        filesystems  loadavg        scsi           version
cgroups    fs           locks          self           version_signature
cmdline    interrupts   mdstat         slabinfo       vmallocinfo
consoles   iomem        meminfo        softirqs       vmstat
cpuinfo    ioports      misc           stat           zoneinfo
crypto     irq          modules        swaps
devices    kallsyms     mounts         sys
diskstats  kcore        mtrr           sysrq-trigger

所以程序似乎再一次变得合理了。如预期一样,你从/bin/bash本身得到了PID “1”,并通过“/bin/ls proc”得到了对应的“80”。是不是比通常的/proc更加nice?这正是我喜欢它的原因。

如果你尝试从namespace直接在“/proc”运行这条命令,它在child中可以运行,但是会BREAK你的主namespace。例子如下:

jean-tiare@jeantiare-Ubuntu:~/blog$ ps aux
Error, do this: mount -t proc proc /proc

这就是PID namespace的全部。有了下一篇文章,我们将能够重新挂载/proc本身,也就可以修复“top”及类似的工具,使之不会破坏parent namespace(父命名空间)。谢谢阅读!

原文链接:Introduction to Linux namespaces – Part 3: PID(翻译:孙科 审校:李颖杰)

原文发布时间为: 2014-12-25

本文作者:codesun

本文来自合作伙伴DockerOne,了解相关信息可以关注DockerOne。

原文标题:Linux命名空间学习教程(三) PID

时间: 2024-12-02 18:31:11

Linux命名空间学习教程(三) PID的相关文章

Linux命名空间学习教程(五)NET

本文讲的是Linux命名空间学习教程(五)NET,[编者的话]Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源.而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid.net.ipc.mnt.uts 等命名空间将容器的进程.网络.消息.文件系统和hostname 隔离开.本文是Linux命名空间系列教程的第五篇,重点介绍NET命名空间.DockerOne在撸代码的基础上进行了校对和整理. 阅读完上一篇关于NS namespac

Linux命名空间学习教程(四)NS(FS)

本文讲的是Linux命名空间学习教程(四)NS(FS),[编者的话]Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源.而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid.net.ipc.mnt.uts 等命名空间将容器的进程.网络.消息.文件系统和hostname 隔离开.本文是Linux命名空间系列教程的第四篇,重点介绍NS(FS)命名空间.DockerOne在撸代码的基础上进行了校对和整理. 继上一篇 关于PID na

Linux命名空间学习教程(一) UTS

本文讲的是Linux命名空间学习教程(一) UTS,[编者的话]Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源.而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid.net.ipc.mnt.uts 等命名空间将容器的进程.网络.消息.文件系统和hostname 隔离开.本文是Linux命名空间系列教程的第一篇,通过一个简单的例子介绍了Linux容器以及UTS命名空间.DockerOne在撸代码的基础上进行了校对和整理. 我

MyBatis学习教程(三)-MyBatis配置优化_java

一.连接数据库的配置单独放在一个properties文件中 之前,我们是直接将数据库的连接配置信息写在了MyBatis的conf.xml文件中,如下: <?xml version="." encoding="UTF-"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config .//EN" "http://mybatis.org/dtd/mybatis--

Docker应用容器基础技术:Linux Namespace 学习教程

我们开始.先从Linux Namespace开始.  简介 Linux Namespace是Linux提供的一种内核级别环境隔离的方法.不知道你是否还记得很早以前的Unix有一个叫chroot的系统调用通过修改根目录把用户jail到一个特定目录下chroot提供了一种简单的隔离模式chroot内部的文件系统无法访问外部的内容.Linux Namespace在此基础上提供了对UTS.IPC.mount.PID.network.User等的隔离机制. 举个例子我们都知道Linux下的超级父亲进程的P

Docker应用容器基础技术:Linux CGroup 学习教程

虽然你通过Namespace把我Jail到一个特定的环境中去了,但是我在其中的进程使用用CPU.内存.磁盘等这些计算资源其实还是可以随心所欲的.所以,我们希望对进程进行资源利用上的限制或控制.这就是Linux CGroup出来了的原因. Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU.内存.磁盘输入输出等).这个项目最早是由Google的工程师在2006年发起(主要是Paul Menage和Roh

Linux命令学习教程

linux基础命令(1) ls命令 linux基础命令(2) cd命令 linux基础命令(3) pwd命令 linux基础命令(4) mkdir命令 linux基础命令(5) rm命令 linux基础命令(6) rmdir命令 linux基础命令(7) mv命令 linux基础命令(8) cp命令 linux基础命令(9) touch命令 linux基础命令(10) cat命令 linux基础命令(11) nl命令 linux基础命令(12) more命令 linux基础命令(13) less

ASP.NET MVC 5 学习教程:添加验证

原文 ASP.NET MVC 5 学习教程:添加验证 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控制器访问模型的数据 生成的代码详解 使用 SQL Server LocalDB Edit方法和Edit视图详解 添加查询 Entity Framework 数据迁移之添加字段 添加验证 Details 和 Delete 方法详解 在本节中,我们将为Movie模型添加验证逻辑,并确认验证规则在用户试图

在Linux系统安装Mysql教程_Mysql

引言 现在因为项目的需要在搭建Mysql的集群,从最简单的开始,先安装一个Mysql 在linux系统下. 步骤: 第一步:安装: tarmysql-5.5.48-linux2.-x86_64.tar.gz Copy到指定的路径下: cpmysql-5.5.48-linux2.6-x86_64 /usr/local/mysql -r 添加系统mysql组合mysql用户: 执行命令:groupaddmysql和useradd -r -g mysql mysql 安装数据库: 进入安装mysql软