我正试图在两个linux命名空间中运行相同的程序。
程序需要读取和写入文件/tmp/server.log。
所以我想确保程序A读/写server.log,但实际上它读和写/tmp/server-A.log。对于程序B读/写server.log,它实际上读和写/tmp/server-B.log。
我尝试使用mount,但没有成功。。。有人能帮我吗?或者我有没有其他方法可以提供文件隔离,这样两个程序就不会真正读/写同一个文件?
#define _GNU_SOURCE
#include<sched.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
static int child_func(void* arg) {
system("mount --bind /tmp ./a");
FILE* file;
file = fopen("/tmp/server.log","rw");
// write some log ...
return 0;
}
static int child2_func(void* arg) {
system("mount --bind /tmp ./b");
file = fopen("/tmp/server.log","rw");
// write some log....
return 0;
}
int main(int argc, char** argv) {
// Allocate stack for child task.
const int STACK_SIZE = 1 * 1024 * 1024;
char* stack = malloc(STACK_SIZE);
char* stack2 = malloc(STACK_SIZE);
if (!stack || !stack2) {
perror("malloc");
exit(1);
}
pid_t pid,pid2;
if ((pid = clone(child_func, stack + STACK_SIZE, CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWNET | SIGCHLD, NULL)) == -1) {
perror("clone");
exit(1);
}
if ((pid2 = clone(child2_func, stack2 + STACK_SIZE, CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWNET | SIGCHLD, NULL)) == -1) {
perror("clone");
exit(1);
}
waitpid(pid,NULL,0);
waitpid(pid2,NULL,0);
return 0;
}
更新:我根据下面回答的解决方案解决了这个问题!他们的解决方案真的帮助了我!
您想要这样的东西:
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <unistd.h>
int doChild(const char *source) {
if(unshare(CLONE_NEWNS)) {
perror("unshare");
return 1;
}
if(mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
perror("mount");
return 1;
}
if(mount(source, "/tmp/server.log", NULL, MS_BIND, NULL)) {
perror("mount");
return 1;
}
execlp("myunmodifiablepythonscript", "myunmodifiablepythonscript", (char*)NULL);
perror("execlp");
return 1;
}
int main(void) {
pid_t pidA, pidB;
pidA = fork();
if(pidA < 0) {
perror("fork");
return 1;
} else if(pidA == 0) {
return doChild("/tmp/server-A.log");
}
pidB = fork();
if(pidB < 0) {
perror("fork");
/* n.b.: pidA will still be running as an orphan. */
return 1;
} else if(pidB == 0) {
return doChild("/tmp/server-B.log");
}
waitpid(pidA, NULL, 0);
/* n.b.: if pidB finishes first, it will be a zombie until pidA finishes. */
waitpid(pidB, NULL, 0);
return 0;
}
几个注意事项:
- 正确使用
clone
(你没有(是一件痛苦的事。只使用fork
然后再使用unshare
要容易得多 - systemd愚蠢地默认共享挂载,这基本上使挂载命名空间什么都不做(即,更改将传播回其他命名空间,从而破坏私有命名空间的用途(。
mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL)
取消了这一点,使它们实际工作 - 我不确定你们想绑什么坐骑,但这是错误的。正确的做法是将单个日志装载到共享名称中
-
您需要将root重新安装到private。检查此链接。
-
当你做
--bind
时,你需要用相反的方式来做。
static int child_func(void* arg) {
mount("/", "/", NULL, MS_PRIVATE, NULL);
mount("./a", "/tmp", NULL, MS_BIND, NULL);
FILE* file;
file = fopen("/tmp/server.log","w");
return 0;
}
static int child_func(void* arg) {
mount("/", "/", NULL, MS_PRIVATE, NULL);
mount("./b", "/tmp", NULL, MS_BIND, NULL);
FILE* file;
file = fopen("/tmp/server.log","w");
return 0;
}