本文演示 CentOS 7.6:Linux testerfans 3.10.0-1160.45.1.el7.x86_64
前言
目前IPC namespace实现了对System V的共享内存、信号量和消息队列以及POSIX的消息队列隔离。Pipe、FIFO、Signal等并未实现。前面我们通过几篇文章整体的介绍了Linux进程间通信。
Linux IPC:System V 与 POSIX 介绍
Linux IPC:Pipes(管道)
Linux IPC:Named Pipes(命名管道)
Linux IPC:Shared Memory(共享内存)
Linux IPC:Message Queue(消息队列)
Linux IPC:Semaphores(信号量)
另外我们在Linux Namespace:UTS中也对命名空间操作的基本系统调用clone()、unshare()和setns()进行了介绍,本章我们将继续通过示例来理解Linux IPC命名空间。
相关命令
Linux系统内我们可以通过自带的命令行工具来操作IPC资源,包括资源的创建、查看和删除等。
ipcmk:创建IPC资源
通过使用man手册查看,ipcmk 允许我们创建共享内存段、消息队列或信号量数组。
-M, --shmem [size] 创建size指定字节大小的共享内存段。
-S, --semaphore [number] 创建number指定数量的信号量组。
-Q, --queue 创建消息队列。
ipcs:查看IPC资源
ipcs命令可以查看有权限查看的系统IPC资源信息。
-m, --shmems 查看共享内存信息。
-q, --queues 查看消息队列信息。
-s, --semaphores 查看信号量信息。
-a, --all 查看全部信息(默认选项)。
ipcs:查看IPC资源
ipcrm 从系统中删除 System V 进程间通信 (IPC) 对象和相关数据结构。要删除此类对象,您必须是超级用户,或者对象的创建者或所有者。 System V IPC 对象分为三种类型:共享内存、消息队列和信号量。消息队列或信号量对象的删除是立即的(不管是否有任何进程仍然持有该对象的 IPC 标识符)。共享内存只有在所有当前连接的进程都将对象从其虚拟地址空间中分离(shmdt(2))后才会被删除。
-m, --shmem-id <id> 通过shmid删除共享内存。
-M, --shmem-key <key> 通过key值删除共享内存。
-q, --queue-id <id> 通过id删除消息队列。
-Q, --queue-key <key> 通过key值删除消息队列。
-s, --semaphore-id <id> 通过id删除信号量。
-S, --semaphore-key <key> 通过key值删除信号量
-a, --all[=<shm|msg|sem>] 删除全部。
-v, --verbose 打印相信信息,查看执行过程。
unshare:加入到新建命名空间
在Linux Namespace:UTS中我们介绍过unshare()系统调用,作用是将当前进程加入到一个新建的命名空间下,系统unshare命令也是如此。我们通过man手册查看,unshare命令可以实现指定的进程加入到UTS、Mount、IPC、Network、PID、User命名空。unshare大家可以从字面意思进行理解,就是不和父进程共享指定的命名空间,需要进行新建。
-i, --ipc 不共享IPC命名空间。
-m, --mount 不共享Mount命名空间。
-n, --net 不共享Network命名空间。
-p, --pid 不共享PID命名空间。 另请参见 --fork 和 --mount-proc 选项。
-u, --uts 不共享UTS命名空间。
-U, --user 不共享User命名空间。
-f, --fork fork 指定程序作为unshare的子进程,而不是直接运行它。这在创建新的 pid 命名空间时很有用。
--mount-proc[=mountpoint] 在运行程序之前,将proc文件系统挂载到挂载点(默认为/proc)。这在创建新的 pid 命名空间时很有用。它还意味着创建一个新的挂载命名空间,因为/proc挂载会扰乱系统上的现有程序。新的proc文件系统显式挂载为私有(由MS_PRIVATE|MS_REC)。
-r, --map-root-user 仅在当前有效用户和组ID映射到新创建的用户命名空间中的超级用户 UID 和 GID 后,才运行程序。
--propagation private|shared|slave|unchanged 在新的挂载命名空间中递归设置挂载传播标志。默认将传播设置为私有,此功能可以通过unchage的参数禁用。当未请求挂载命名空间 (--mount) 时,这些选项会被静默忽略。
--setgroups allow|deny 允许或拒绝用户命名空间中的 setgroups(2) 系统调用。
nsenter :加入到已存在命名空间
在Linux Namespace:UTS中我们介绍了setns系统调用,他的作用是将指定的进程加入到指定的命名空间内。我们通过nsenter工具也是实现此功能。通过man手册查看nsenter的用法。
-t, --target pid 指定要从中获取上下文的目标进程。 pid 指定的上下文的路径是
/proc/pid/ns/mnt mount 命名空间
/proc/pid/ns/uts UTS 命名空间
/proc/pid/ns/ipc IPC 命名空间
/proc/pid/ns/net network 命名空间
/proc/pid/ns/pid PID 命名空间
/proc/pid/ns/user user 命名空间
/proc/pid/root 根目录
/proc/pid/cwd 工作目录
-m, --mount[=file] 输入挂载命名空间。如果没有指定文件,则进入目标进程的挂载命名空间。如果指定了file,则进入file指定的挂载命名空间。
-u, --uts[=file] 输入 UTS 命名空间。如果未指定文件,则输入目标进程的 UTS 命名空间。如果指定了 file,则输入 file 指定的 UTS 命名空间。
-i, --ipc[=file] 输入 IPC 命名空间。如果未指定文件,则输入目标进程的 IPC 命名空间。如果指定了file,则输入file指定的IPC命名空间。
-n, --net[=file] 输入网络命名空间。如果没有指定文件,则输入目标进程的网络命名空间。如果指定了 file,则输入 file 指定的网络命名空间。
-p, --pid[=file] 输入 PID 命名空间。如果未指定文件,则输入目标进程的 PID 命名空间。如果指定了file,则输入file指定的PID命名空间。
-U, --user[=file] 输入用户命名空间。如果没有指定文件,则输入目标进程的用户命名空间。 如果指定了文件,则输入文件指定的用户命名空间。另请参见 --setuid 和 --setgid 选项。
-S, --setuid uid 设置将在输入的命名空间中使用的用户 ID。 nsenter(1) 总是为用户命名空间设置 UID,默认为 0。
--preserve-credentials 进入用户命名空间时不要修改 UID 和 GID。默认是删除补充组并将 GID 和 UID 设置为 0。
-r, --root[=directory] 设置根目录。如果不指定目录,则将根目录设置为目标进程的根目录。如果指定了目录,则将根目录设置为指定目录。
-w, --wd[=directory] 设置工作目录。如果不指定目录,则将工作目录设置为目标进程的工作目录。如果指定了目录,则将工作目录设置为指定的目录。
-F, --no-fork 在执行指定的程序之前不要fork。默认情况下,当进入 PID 命名空间时,nsenter 在调用 exec 之前调用 fork,这样任何子节点也将在新进入的 PID 命名空间中。
-Z, --follow-context 根据 --target PID 指定的已运行进程设置用于执行新进程的 SELinux 安全上下文。 (util-linux 必须在 SELinux 支持下编译,否则该选项不可用。)
演示
接下来我们将使用ipc相关、unshare和nsenter命令行来简单演示一下IPC命名空间的隔离。为了方便对比效果,我们将终端拆分成两个窗口,左侧为shell1,右侧为shell2。
- 在两个shell中使用readlink /proc/$$/ns/ipc确认是否在相同的命名空间内。
图中显示,此时两个shell进程在相同的命名空间内。
- 在shell2中通过unshare -i指令将shell2加入到新建的IPC命名空间内。
执行unshare -i 指令后,shell2的ipc命名空间发现变化。
- 在shell2中通过ipcmk指令来创建ipc资源,并分别在两个shell中进行查看。
图中显示,在shell2中使用ipcmk创建了信号量后,我们通过ipcs查看ipc资源发现,shell1和shell2的ipc资源并不相同。
- 在shell2中通过nsenter指令将shell1加入到shell2中,再分别查看ipc资源。
图中显示,在shell1中执行了nsenter指令后先运行了一个新的shell并加入到了shell2的ipc命名空间内,通过查看也可以发现两个shell的ipc命名空间也保持了一致,其他命名空间未发生改变。
总结
通过之前IPC和Namespace相关操作的介绍,我们在本篇简单的对IPC命名空间实现IPC相关资源隔离进行了演示。后续我们将继续来探索其他的命名空间。
本文参考:
Linux Namespace:IPC
man手册
评论区