我正在尝试使用新的命名空间创建一个进程,为此我需要使用带有适当标志的 clone(2),以下是 clone 系统调用和 printf() 语句来打印父 PID:
printf("clone() = %ld\n", (long)getpid());
printf("PID: %ld\n", (long)getpid());
struct utsname utsname;
uname(&utsname);
printf("parent namespace hostname: %s\n", utsname.nodename);
clone(child_main(&process_struct, checkpoint), stack + process_struct.Stack,
CLONE_NEWCGROUP
|CLONE_NEWIPC
|CLONE_NEWNET
|CLONE_NEWNS
|CLONE_NEWPID
|CLONE_NEWUTS|SIGCHLD, &process_struct)
和 child_main() 函数,子函数会设置主机名,然后会打印子进程的 PID,问题是系统的主机名改变的不仅仅是命名空间的主机名,而且子进程的 PID 与父进程的 PID 相同,这个错误,命名空间内的子 PID 应为 1,其 PPID 为 0(表示没有父进程),sethostname(2) 也只能影响子进程命名空间
int child_main(struct process *process, int *checkpoint){
char c;
fprintf(stderr,"=> IPC setup...");
//double check the IPC
close(checkpoint[1]);
fprintf(stderr,"Done\n");
if ( sethostname(process->Hostname, strlen(process->Hostname)){
//close(process->File_descriptor);
return -1;
}
printf("PID: %ld\n", (long)getpid());
struct utsname utsname;
uname(&utsname);
printf("child namespace hostname: %s\n", utsname.nodename);
// startup the IPC pipes
read(checkpoint[0], &c, 1);
char* argv[]={(char*)0};
if(execve("/bin/bash", argv, NULL) == -1 ){
fprintf(stderr,"--> Launching process Failed %m\n");
return -1;
}
return 0;
}
glibc 包装器将
clone()
函数指针作为第一个参数。您没有传递给它一个函数指针,而是一个
int
(在调用克隆之前child_main
在父进程中调用的 的返回)。如果传递一个指针作为第一个参数(从你的返回),它将返回 -1 并设置为,但我猜你没有检查它的返回值。child_main
NULL
0
child_main
errno
EINVAL
从
clone()
手册页:因此,
child_main
将在父进程中运行,不会创建子进程或命名空间,并将child_main
主机名设置在初始命名空间中,即为您的整个机器设置。