Linux下clone函数

Liunx下clone函数分析

动机

上一篇探究fork()、vfork()、pthread()的区别,以及每个函数创建子进程后与父进程的联系。
这一篇探究clone函数

clone

参数:

 int clone(int (*fn)(void *fnarg), void *child_stack, int flags, void *arg, ...
                 /* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );

fn是指向子进程执行时调用的函数,fnarg是可以传给该函数的参数,child_stack是为子进程分配的堆栈指针,arg是传给子进程的参数一般为0.

下面是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线程标准,子进程与父进程共享相同的线程群

原文链接:https://blog.youkuaiyun.com/gogokongyin/article/details/51178257

clone11Test.c

#define  _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#include <sched.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>


#define FIBER_STACK 8192
int global_a;
void * stack;

int do_something(){
   
   
    printf("This is son, the pid is:%d, the a is: %d\n", getpid(), ++global_a);
    free(stack); //这里我也不清楚,如果这里不释放,不知道子线程死亡后,该内存是否会释放,知情者可以告诉下,谢谢
    exit(1);
}

int main(){
   
   

    global_a = 1;
    stack = malloc(FIBER_STACK);//为子进程申请系统堆栈

    if(!stack)
    {
   
   
        printf("The stack failed\n");
        exit(0);
    }
    printf("creating son thread!!!\n");

    clone(&do_something, (char *)stack + FIBER_STACK, CLONE_VM|CLONE_VFORK, 0);//创建子线程

    printf("This is father, my pid is: %d, the global_a is: %d\n", getpid(), global_a);
    exit(1);
}

输出

This is son, the pid is:26369, the a is: 2
This is father, my pid is: 26368, the a is: 2

结果分析
clone中的参数CLONE_VM|CLONE_VFORK,这里实验了两个参数,从输出结果的顺序上可看出子线程是运行在父进程之前,在数值上可以看出两个进程共享的内存空间。
猜想:子进程运行在父进程之前 是由于输出时间太快导致的巧合,还是子进程会阻塞父进程,由下一个实验验证

clone12Test.c

#define  _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#include <sched.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>


#define FIBER_STACK 8192
#define CLONE_NUM 5

int global_a;
void * stacks[CLONE_NUM];

int do_something(void *lparam){
   
   
    int i;
    i = *((int *)lparam);
    printf("This is son, the pid is:%d, the global_a is: %d\n", getpid(), ++global_a);
    printf("start to do loop! This is son, the pid is:%d, the param is: %d\n", getpid(), i);   
    
    do_loop_time(); //
    printf("do loop end! This is son, the pid is:%d, the global_a is: %d\n  ", getpid(), ++global_a);
    
    free(stacks[i]); //这里我也不清楚,如果这里不释放,不知道子线程死亡后,该内存是否会释放,知情者可以告诉下,谢谢
    exit(1);
}

int do_loop_time(){
   
   
    int i,j,k;
    
    for (i=0;i<1000;i++)
	for (j=0;j<1000;j++)
	    for (k=0;k<1000;k++)
		;
}

int main(){
   
   
    int i;
    global_a = 0;
    
    for (i=0;i<CLONE_NUM;i++)  {
   
   
	stacks[i] = malloc(FIBER_STACK);//为子进程申请系统堆栈   
        if(!stacks[i]) {
   
   
			printf("The stack failed\n");
			exit(0);
	    }
    }

    printf("creating son thread!!!\n");
    for (i=0;i<CLONE_NUM;i++)   {
   
   
		clone(&do_something, (char *)(stacks[i]) + FIBER_STACK, CLONE_VM|CLONE_VFORK, &i);//创建子线程   
    }
    

    printf("This is father, my pid is: %d, the global_a is: %d\n", getpid(), global_a);
    
     for (i=0;i<CLONE_NUM;i++)    {
   
   
//		free(stacks[i]) ;   
    }   
  
    exit(1);
}

输出

creating son thread!!!
This is son, the pid is:19144, the global_a is: 1
start to do loop! This is son, the pid is:19144, the param is: 0
do loop end! This is son, the pid is:19144, the global_a is: 2

This is son, the pid is:19145, the global_a is: 3
start to do loop! This is son, the pid is:19145, the param is: 1
do loop end! This is son, the pid is:19145, the global_a is: 4

This is son, the pid is:19146, the global_a is: 5
start to do loop! This is son, the pid is:19146, the param is: 2
do loop end! This is son, the pid is:19146, the global_a is: 6

This is son, the pid is:19147, the global_a is: 7
start to do loop! This is son, the pid is:19147, the param is: 3
do loop end! This is son, the pid is:19147, the global_a is: 8

This is son, the pid is:19148, the global_a is: 9
start to do loop! This is son, the pid is:19148, the param is: 4
do loop end! This is son, the pid is:19148, the global_a is: 10

This is father, my pid is: 19143, the global_a is: 10

结果分析
创建了5个子进程,从开始执行循环和循环结束的语句中可以看出子进程之间是串行运行,父进程将会被阻塞直到所有子进程运行完毕。

clone13Test.c

#define  _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#include <sched.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>


#define FIBER_STACK 8192
#define CLONE_NUM 5

int global_a;
void 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值