我正在尝试实现一个容器,为此我使用带有适当标志的clone(2)系统调用创建一个进程:
if ((child_pid = clone(child_main, process_struct.Stack + process_struct.StackPtr,
CLONE_NEWCGROUP
|CLONE_NEWIPC
|CLONE_NEWNET
|CLONE_NEWNS
|CLONE_NEWPID
|CLONE_NEWUTS
|SIGCHLD, &process_struct, checkpoint)) == -1){
fprintf(stderr,"Failed...%m \n");
exit(EXIT_FAILURE);
}else{
fprintf(stderr,"Done\n");
waitpid(child_pid, NULL, 0);
}
在 child_main() 内部,我更改了进程命名空间的主机名,还设置了挂载命名空间,我在分区上安装了 Linux 文件系统层次结构,就像正常的 Linux 安装一样(我这样做是为了创建一个干净的文件系统映像,其中包含我的文件和二进制文件),然后将传播类型设置为 MS_UNBINDABLE,然后使用ivot_root(2) 更改进程的根目录。
const int child_main(struct process *process_struct, int *checkpoint){
char c;
fprintf(stderr,"=> IPC setup...");
//double check the IPC
close(checkpoint[1]);
fprintf(stderr,"Done\n");
if ( sethostname(process_struct->Hostname,
strlen(process_struct->Hostname)) || mounting(process_struct)){
return -1;
}
// startup the IPC pipes
read(checkpoint[0], &c, 1);
if(execve("/bin/bash", (char*)0, NULL) == -1 ){
fprintf(stderr,"--> Launching process Failed %m\n");
return -1;
}
return 0;
}
问题是我的系统执行了 execve(2) 并且没有启动 /bin/bash 并且程序运行没有错误。当我在 execve(2) 之前添加 system(2) 语句时:system("ls");
它列出了适当的文件系统和当前工作目录。此外,当我将 execve(2) 参数更改为:
execve("/bin/ls", (char*)0, NULL)
或execve("/bin/pstree", (char*)0, NULL)
或任何其他参数时,它将返回错误:没有这样的文件或目录或者通过 exec 系统调用传递了 NULL argv[0],当我在 execve(2) 系统调用中 strace 我的程序时,它给出:空、0、空)= 17992
更新:该错误与文件系统映像无关,我已经执行了更多测试,如下所示,我用于挂载命名空间的是我系统的文件系统,而不是我安装在分区上并运行 /bin/bash 的文件系统。仍然可以工作,我创建了一个简单的 C 程序并编译了它,它运行良好,所以有一些错误阻止了 bin/bash 的执行,为了进一步测试这些结果,我将文件系统重新用于我的挂载命名空间,我移动了第一个文件系统的相同可执行文件位于同一路径下"/"
,第二个文件系统位于同一路径下
我的可执行文件的主系统路径= /home/omar/docs/test.out
我从分区路径到可执行文件的安装文件系统= /home/omar/docs/test.out
因为我想检查在向每个可执行文件添加一条语句时是否相同的路径可能会引起混乱,这样就可以知道我的程序采用了哪条路径,并且它工作正常,没有任何问题并且按预期正确,所以问题只是该系统基本命令将不起作用。