我正在尝试使用新的命名空间创建一个进程,为此我需要使用带有适当标志的clone(2),以下是clone系统调用和打印父PID的printf()语句:
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;
}
答案1
glibcclone()
包装器将函数指针作为第一个参数。
您没有向它传递一个函数指针,而是一个(在父进程中调用的int
返回值,child_main
前调用克隆)。如果child_main
传递一个NULL
指针作为第一个参数(0
从您的返回child_main
),它将返回 -1 并设置errno
为EINVAL
,但我猜您没有检查它的返回值。
从clone()
联机帮助页:
EINVAL
当or指定为 NULL时,由 glibcclone()
包装函数返回。fn
child_stack
因此,child_main
将在父进程中运行,不会创建任何子进程或命名空间,并child_main
在初始命名空间中设置主机名,即为您的整个机器设置主机名。