linux容器基础-namespace-3(pid)

ops/2024/9/23 14:31:57/

namespace_0">pid namespace

pid namespace表示隔离一个具有独立PID的运行环境。
在每一个pid namespace中,进程的pid都从1开始,且和其他pid namespace中的PID互不影响。
这意味着,不同pid namespace中可以有相同的PID值。

在介绍pid namespace之前,先创建其他类型的namespace然后查看进程关系:

#在root namesapce查看当前进程的id是4048028
root@ubuntu-server:~# echo $$
4048028root@ubuntu-server:~# pstree -p |grep 4048028
|-sshd(3944519)---sshd(4047935)---bash(4048028)-+-grep(4074182)#进程的关系:
#systemd(1) |-sshd(3944519 这个是sshd服务server)|-sshd(4047935,这个是ssh连接的进程)|---bash(4048028)-+-grep(4074182)root@ubuntu-server:~# ps -ef|grep 3944519
root     3944519       1  0 Jan15 ?        00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

创建一个uts namespace

root@ubuntu-server:~# unshare -u /bin/bash

在uts namespace中查看当前进程

root@ubuntu-server:~# pstree -p |grep grep
|-sshd(3944519)---sshd(4047935)---bash(4048028)---bash(4074716)-+-grep(4074764)root@ubuntu-server:# ls -l /proc/4074716/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 15:07 uts -> uts:[4026532372]
root@ubuntu-server:# ls -l /proc/4048028/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 11:17 uts -> uts:[4026531838]
root@ubuntu-server:~# ls -l /proc/4047935/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 11:17 uts -> uts:[4026531838]#从上面输出的结果可知,创建uts类型namespace时,unshare进程会在创建新的namespace后被该namespace中的第一个进程给替换掉。
#并且我们可以看到unshare创建的bash(4074716)进程与其父进程(4048028),2者的uts namespace是不一致的。

创建pid namespace

unshare --pid --fork [--mount-proc] <CMD>
--pid(-p):    表示创建pid namespace
--mount-proc: 表示创建pid namespace时重新挂载procfs
--fork(-f):   表示创建pid namespace时,不是直接替换unshare进程,而是fork unshare进程,并使用CMD替换fork出来的子进程

我们使用fork的参数来验证一下:

root@ubuntu-server:~# echo $$
4048028root@ubuntu-server:# unshare -p -f  --mount-proc /bin/bash
root@ubuntu-server:# pstree -p |grep grep
bash(1)-+-grep(9)#终端2,重新打开一个终端
root@ubuntu-server:~# pstree -p 4048028
bash(4048028)───unshare(4090558)───bash(4090559)root@ubuntu-server:# ls -l /proc/4048028/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 11:17 /proc/4048028/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:# ls -l /proc/4090558/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 17:27 /proc/4090558/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l /proc/4090559/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 17:27 /proc/4090559/ns/pid -> 'pid:[4026532379]'#通过这个实验,我们可以看到unshare(4090558)这个进程还是在原来的namespace,并不会加入新的namespace
而fork出来的bash(4090559)进程,他是加入到了一个新的namespace当中。

嵌套pid namespace

这个很容易理解,就是不同namespace之间可以相互嵌套,所有的子孙pid namespace中的进程信息都会保存在父级以及祖先级namespace中,
只不过在不同嵌套层级中,同一个进程对应的PID不同。

#我们这里在namespace1之中在创建一个namespace2看看进程的关系是什么样的
#------第一个终端------
#namespace1
root@ubuntu-server:~# unshare -p -f -u --mount-proc /bin/bash
root@ubuntu-server:~# hostname namespace1
root@ubuntu-server:~# exec bash#在namespace1中创建namespace2
root@namespace1:~# unshare -p -f -u --mount-proc /bin/bash
root@namespace1:~# hostname namespace2
root@namespace1:~# exec bash
root@namespace2:~# pstree -p |grep grep
bash(1)-+-grep(16)##------第二个终端------,也就是root namespace下面
root@ubuntu-server:~# pstree -p 4048028
bash(4048028)───unshare(4097920)───bash(4097921)───unshare(4098083)───bash(4098084)#在上面fork测试中我们知道unshare进程还在原来的namespace,而unshare创建的bash是在新的namespace中。
所以bash(4048028)───unshare(4097920)在同一个ns,bash(4097921)───unshare(4098083)在同一个ns,bash(4098084)在一个nsroot@ubuntu-server:~# ls -l -h  /proc/4048028/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 11:17 /proc/4048028/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l -h  /proc/4097920/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4097920/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l -h  /proc/4097921/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4097921/ns/pid -> 'pid:[4026532386]'
root@ubuntu-server:~# ls -l -h  /proc/4098083/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4098083/ns/pid -> 'pid:[4026532386]'
root@ubuntu-server:~# ls -l -h  /proc/4098084/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4098084/ns/pid -> 'pid:[4026532391]'

pid namespace和procfs

/proc目录是内核对外暴露的可供用户查看或修改的内核中所记录的信息,包括内核自身的部分信息以及每个进程的信息。
比如对于pid=N的进程来说,它的信息保存在/proc/目录下。在操作系统启动的过程中,会挂载procfs到/proc目录,它存在于root namespace中。
但是,创建新的pid namespace时不会自动重新挂载procfs,而是直接拷贝父级namespace的挂载点信息。
这使得在新的pid namespace中仍然保留了父级namespace的/proc目录,也就是在新创建的这个pid namespace中仍然保留了父级的进程信息。

#不挂载 --mount-proc此时namespace还是继承宿主机的进程树
root@ubuntu-server:~# unshare -p -u -f /bin/bash
root@ubuntu-server:~# hostname namepsace1
root@ubuntu-server:~# exec bash
root@namepsace1:~# pstree
systemd─┬─ModemManager───2*[{ModemManager}]├─agetty├─cron├─dbus-daemon├─dnsmasq───dnsmasq├─irqbalance───{irqbalance}......

之所以有上述问题,其原因是在pid namespace中保留了root namespace中的/proc目录,而不是属于pid namespace自己的/proc。
但用户创建pid namespace时希望的是有完全独立的进程运行环境。
这时,需要在pid namespace中重新挂载procfs,或者在创建pid namespace时指定–mount-proc选项。

# 注意这儿添加了mount-proc参数
root@ubuntu-server:~# unshare -p -u -f --mount-proc /bin/bash
root@ubuntu-server:~# hostname namespace1
root@ubuntu-server:~# exec bash# 进程树中展示了bash 为init进程
[root@namespace1 ~]# pstree -p
bash(1)───pstree(24)

pid namespace信号量

pid=1的进程是每一个pid namespace的核心进程(init进程),它不仅负责收养其所在pid namespace中的孤儿进程,还影响整个pid namespace

当pid namespace中pid=1的进程退出或终止,内核默认会发送SIGKILL信号给该pid namespace中的所有进程以便杀掉它们(如果该pid namespace中有子孙namespace,也会直接被杀)。

在创建pid namespace时可以通过–kill-child选项指定pid=1的进程终止后内核要发送给pid namespace中进程的信号,其默认信号便是SIGKILL。

root@ubuntu-server:~# lsns
4026532379 pid         1 4099754 root             bashroot@ubuntu-server:~# kill -9 4099754
#在namespace1的进程,kill掉这个进程后这个namespace1整个namespace都被干掉了
root@namepsace1:~# Killed#也可以指定为其他信号
unshare -p -f -m -u --mount-proc --kill-child=SIGHUP /bin/bash

我们在这里通过一些简单的例子来熟悉了一下pid namespace是如何工作的,当以后我们在玩k8s和docker的时候看到容器中的进程
是如何与宿主机隔离的就不会感到疑惑了。


http://www.ppmy.cn/ops/97977.html

相关文章

消防设施操作员考试真题题库及答案

消防设施操作员考试真题题库及答案 41.&#xff08;&#xff09;指既能喷射充实的水流&#xff0c;又能喷射雾状水流&#xff0c;是具有开启、关闭功能的水枪。它机动性能好&#xff0c;对火场适应性好。 A.直流开花水枪 B.喷雾水枪 C.直流喷雾水枪 D.多功能水枪 答案&am…

安科瑞ACREL-7000能源管控平台在综合能耗监测系统在大型园区的应用

摘要&#xff1a;大型综合园区已经成为多种能源消耗的重要区域&#xff0c;为了探索适用于大型综合园区的综合能耗监测系统&#xff0c;建立了综合能耗监测系统整体框架&#xff0c;提出了综合能耗网络、能耗关系集合、能耗均衡度等概念&#xff0c;并以某大型综合园区为例对综…

URP平面阴影合批处理 shadow

闲谈 相信大家在日常工作中发现了一个问题 &#xff0c; urp下虽然可以做到3个Pass 去写我们想要的效果&#xff0c;但是&#xff0c;不能合批&#xff08;不能合批&#xff0c;那不是我们CPU要干冒烟~&#xff01;&#xff09; 好家伙&#xff0c;熊猫老师的偏方来了 &#x…

Docker 离线下载镜像(本地)

最近很多离线下载镜像的网站挂了&#xff0c;可以选择 docker hub 下载上传到服务器 Docker desktop image-tools ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/04174b8cefe3445596e09b1e82d9253b.png 保存后&#xff0c;就可以上传服务器&#xff0c;通过 dock…

打卡50天------图论

正式开启图论了&#xff0c;作为一个前端工程师&#xff0c;这个代码随想录真的刷新了我对于算法的认知&#xff0c;每天都在学习新东西。 别着急、放轻松、慢慢来。 一、图论理论基础 二、深搜理论基础 了解一下深搜的原理和过程&#xff0c;其实对于深搜和广搜我自己也写过…

Spring OAuth2.0客户端源码解析

主要分析spring-security-oauth2-client的源码&#xff0c;介绍OAuth2.0授权码模式下Spring Boot OAuth2客户端的运行流程 代码版本信息 Spring Boot 2.7.10 spring-security-oauth2-client 5.7.7流程 在 Spring Security OAuth2 Client 中&#xff0c;多个过滤器协同工作以处…

《SpringSecurity 速速上手》

本笔记学习于&#xff1a;哔哩哔哩 三更草堂&#x1f449;、感谢大佬、三更せんせい&#xff0c;录制分享&#x1f4fc;&#x1f9ce;‍♂️&#x1f9ce;‍♂️&#x1f9ce;‍♂️ 可能设计的知识&#xff1a; JWT令牌、会话控制、blog中涉及其他内容&#xff0c;可以直接跳…

Appium定位元素

使用工具&#xff1a; 报错: Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn‘t 参考链接&#xff1a;Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn‘t-CSD…