这里fn是函数指针,我们知道进程的4要素,这个就是指向程序的指针,就是所谓的“剧本";child_stack是为子进程分配堆栈空间, 无论子进程是否与父进程共享内存空间,该指针都不能为NULL,否则,无法创建子进程。由于linux中栈是栈底在高地址,所以,应将栈底的地址传给clone函数。flags就是标志用来描述你需要从父进程继承那些资源, arg就是传给子进程的参数)。下面是flags可以取的值
标志 含义
CLONE_PARENT 创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子”
CLONE_FS 子进程与父进程共享相同的文件系统,包括root、当前目录、umask
CLONE_FILES 子进程与父进程共享相同的文件描述符(file descriptor)表
CLONE_NEWNS 在新的namespace启动子进程,namespace描述了进程的文件hierarchy
CLONE_SIGHAND 子进程与父进程共享相同的信号处理(signal handler)表
CLONE_PTRACE 若父进程被trace,子进程也被trace
CLONE_VFORK 父进程被挂起,直至子进程释放虚拟内存资源
CLONE_VM 子进程与父进程运行于相同的内存空间
CLONE_PID 子进程在创建时PID与父进程一致
CLONE_THREAD Linux 2.4中增加以支持POSIX线程标准,子进程与父进程共享相同的线程群
下面的例子是创建一个线程(子进程共享了父进程虚存空间,没有自己独立的虚存空间不能称其为进程)。父进程被挂起当子线程释放虚存资源后再继续执行。
#define _GNU_SOURCE
#include "sched.h"
#include "stdio.h"
#include "signal.h"
#define CHILD_STACK 8192
int a;
void * stack;
int childFunc(){
++a;
printf("[Child] a=%d\n", a);
exit(0);
}
int main() {
char * stack;
a = 1;
stack = (char*) malloc(CHILD_STACK );//为子进程申请系统堆栈
if(!stack) {
printf("malloc failed/n");
exit(0);
}
printf("create child thread...\n");
clone(childFunc, stack + CHILD_STACK , CLONE_VM|CLONE_VFORK, 0);//创建与父进程共享用户空间的子进程,因而,是一个线程
printf("[Parent] a=%d\n", a);
exit(0);//此处,自动释放stack所指空间
}
由于clone函数是linux扩展POSIX的函数,而非POSIX标准函数,因此,需要在文件头声明宏_GNU_SOURCE,表明该代码不保证可移植性。
sched.h文件是clone函数的声明文件,需要添加。
程序执行结果:
create child thread...
[Child] a=2
[Parent] a=2