呼叫"克隆()"在Linux上,但它似乎出现故障

时间:2017-01-11 01:48:38

标签: linux gcc process gdb clone

一个简单的测试程序,我希望它会"克隆"分叉子进程,每个进程都可以执行直到结束

SELECT *. 
FROM PersonalTable
INNER JOIN ON Employees.PersonalID = PersonalTable.PersonalID 
WHERE PersonalID = " + PersonalID.ToString()

茹:

#include<stdio.h>
#include<sched.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
int f(void*arg)
{
pid_t pid=getpid();
printf("child pid=%d\n",pid);
}
char buf[1024];
int main()
{
    printf("before clone\n");
    int pid=clone(f,buf,CLONE_VM|CLONE_VFORK,NULL);
    if(pid==-1){
        printf("%d\n",errno);
        return 1;
    }
    waitpid(pid,NULL,0);
    printf("after clone\n");
    printf("father pid=%d\n",getpid());
    return 0;
}

它没有打印出我的预期。似乎&#34;克隆&#34;程序处于未知状态,然后退出。我尝试了gdb并打印出来:

$g++ testClone.cpp && ./a.out
before clone

如果我删除&#34; waitpid&#34;的行,那么gdb会打印另一种奇怪的信息。

Breakpoint 1, main () at testClone.cpp:15
(gdb) n-
before clone
(gdb) n-
waiting for new child: No child processes.
(gdb) n-
Single stepping until exit from function clone@plt,-
which has no line number information.

我的课程在哪里出错?

2 个答案:

答案 0 :(得分:2)

您永远不应该在用户级程序中调用clone - 对于您在clone进程中可以执行的操作有太多限制。

特别是,调用任何libc函数(例如printf)都是完全禁忌(因为libc不知道您的clone存在,并且没有进行任何设置)。

正如K. A. Buhr所指出的那样,你也传递了太小的筹码,而且错误的结局。你的堆栈也没有正确对齐。

简而言之,尽管K. A. Buhr的修改出现,但实际上并非如此。

TL; DR:clone,只是使用它。

答案 1 :(得分:1)

clone的第二个参数是指向子堆栈的指针。根据{{​​1}}的手册页:

  

在运行Linux的所有处理器(HP PA处理器除外)上堆栈向下增长,因此child_stack通常指向为子堆栈设置的内存空间的最顶层地址。

此外,1024字节对于堆栈来说是微不足道的数量。以下修改后的程序版本似乎正常运行:

clone(2)

另外,@Employed Russian是对的 - 你可能不应该使用// #define _GNU_SOURCE // may be needed if compiled as C instead of C++ #include <stdio.h> #include <sched.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> int f(void*arg) { pid_t pid=getpid(); printf("child pid=%d\n",pid); return 0; } char buf[1024*1024]; // *** allocate more stack *** int main() { printf("before clone\n"); int pid=clone(f,buf+sizeof(buf),CLONE_VM|CLONE_VFORK,NULL); // *** in previous line: pointer is to *end* of stack *** if(pid==-1){ printf("%d\n",errno); return 1; } waitpid(pid,NULL,0); printf("after clone\n"); printf("father pid=%d\n",getpid()); return 0; } ,除非你想尝试一些乐趣。 clonefork只要满足您的需求,就会vfork更明智地与clone接口。