我有以下代码:
#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 char child_stack[2048];
int x = 10;
static int child_fn() {
printf("Pid: %ld\n", (long) getpid());
return 0;
}
int main() {
printf("before= %d\n", x);
errno = 0;
pid_t child_pid = clone(&child_fn, (void *) child_stack+1024, CLONE_NEWPID | SIGCHLD, NULL);
if(child_pid == -1) {
printf("%s\n", strerror(errno));
return 0;
} else {
printf("clone()= %ld\n", (long) child_pid);
printf("after= %d\n", x);
while(waitpid(-1, NULL, 0) < 0 && errno == EINTR) {
printf("waiting\n");
continue;
}
return 0;
}
}
我得到的输出是:
before= 10
clone()= 16
after= 10
这意味着child_fn
确实被分配了一个Pid,即child_pid
。但printf
内的child_fn
要么没有执行,要么可能在不同的标准范围内打印?无论哪种方式,可能是什么原因,以及如何调试它。我只是从命名空间开始,所以不太了解它们。
答案 0 :(得分:1)
如果我使用gdb
运行原始代码,我发现它失败了SIGSEGV
:
$ gcc -o clone clone.c
$ sudo gdb ./clone
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /home/lars/tmp/clone
before= 10
[New process 10768]
clone()= 10768
after= 10
Thread 2.1 "clone" received signal SIGSEGV, Segmentation fault.
[Switching to process 10768]
0x00007ffff7a5e9de in vfprintf () from /lib64/libc.so.6
我怀疑你的child_stack
太小了。您已经分配了2048个字节,但是您只使用了一半。如果我将clone
调用修改为如下所示:
pid_t child_pid = clone(&child_fn, (void *) child_stack+2048, CLONE_NEWPID | SIGCHLD, NULL);
然后在我的系统上它似乎正确运行:
$ sudo gdb ./clone
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /home/lars/tmp/clone
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.24-9.fc25.x86_64
before= 10
[New process 10807]
clone()= 10807
after= 10
Pid: 1
[Inferior 2 (process 10807) exited normally]