在 Linux 内核命名空间之间使用 POSIX 信号量
Posted
技术标签:
【中文标题】在 Linux 内核命名空间之间使用 POSIX 信号量【英文标题】:Using POSIX semaphores between Linux kernel namespaces 【发布时间】:2021-01-01 23:30:39 【问题描述】:我正在开发一个使用 Linux 命名空间的 C 应用程序,并且出现的一件事是需要使用信号量(或类似的东西)从父命名空间向子命名空间发出信号。这是我目前正在尝试做的事情:
#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <semaphore.h>
//A stack for the container
#define STACK_SIZE (1024 * 1024)
static char stack[STACK_SIZE];
//The semaphore
sem_t semaphore;
int child(void* arg)
int semval;
//Print the semaphore state as read from the new namespace
for(int i=0;i<6;i++)
sem_getvalue(&semaphore, &semval);
printf("Semaphore state: %d.\n", semval);
sleep(1);
return 1;
int main()
//Init a shared POSIX semaphore with the value zero
sem_init(&semaphore, 1, 0);
//Create the child namespace
pid_t pid = clone(child, stack+STACK_SIZE, CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
//Wait, then post the semaphore
sleep(3);
printf("Posting semaphore\n");
sem_post(&semaphore);
//Wait for it to return
waitpid(pid, NULL, 0);
return 0;
据我了解,这应该在一个新的命名空间中启动 child
,它会在其中多次吐出信号量的值。我们应该能够看到父命名空间中的父进程何时发布它,但是我们看不到:
Semaphore state: 0.
Semaphore state: 0.
Semaphore state: 0.
Posting semaphore
Semaphore state: 0.
Semaphore state: 0.
Semaphore state: 0.
信号量被初始化为共享,从克隆调用中删除 CLONE_NEWIPC
也不能解决这个问题(据我了解,它只处理隔离 SysV IPC,而不是这个 POSIX 信号量)。
另一个怪癖是,如果我们将信号量初始化为不同的值(例如sem_init(&semaphore, 1, 3);
,子命名空间将读取该初始值:
Semaphore state: 3.
Semaphore state: 3.
Semaphore state: 3.
Posting semaphore
Semaphore state: 3.
Semaphore state: 3.
Semaphore state: 3.
因此,它似乎并没有完全无法访问信号量 - 它只是没有看到它何时发布。你应该怎么做?我需要设置一些特殊的共享内存技巧以使其在命名空间之间工作,还是我只是在这里做错了什么?
【问题讨论】:
【参考方案1】:sem_*
假定信号量内存在进程/线程之间共享。
当您clone/fork
时,您会得到不同的副本。
要解决此问题,请将 CLONE_VM
添加到您的标志参数 [首选]。
或者,在执行clone
之前确保信号量在共享内存中(例如mmap
、shmget
等)。
【讨论】:
谢谢!这是由mmap
ing 匿名共享内存完成的,现在可以了。我知道匿名共享内存只能由映射进程及其子进程访问,但是如果有多个子进程,有没有办法控制 哪些 可以访问它?以上是关于在 Linux 内核命名空间之间使用 POSIX 信号量的主要内容,如果未能解决你的问题,请参考以下文章