Linux--进程创建总结
1 fork:子进程是父进程副本,不知道父子进程启动顺序,复制父进程资源。
2 vfork: 不创建子进程了,子进程和父进程共享数据段,创建的子进程先于父进程进行。
3 clone: 创建线程使用pthread库,更精确指定要共享的内容。
fork:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
int count = 1;
int child;
child = fork( );
if(child < 0){
perror("fork failure ");
exit(1);
}else if(child == 0){
printf("This is child, count is: %d (%p). and his pid is: %d\n", ++count, &count, getpid());
}else {
printf("This is parent,count is: %d (%p), his pid is: %d\n", count, &count, getpid());
}
exit(0);
}
1>运行结果里面可以看出父子两个进程的pid不同,堆栈和数据资源都是完全的复制
2>子进程改变了count的值,而父进程中的count没有被改变。
3>子进程与父进程count的地址(虚拟地址)是相同的(在内核中被映射的物理地址不同)
CW技术(写时复制)
一句话
父进程和子进程都设置成了只读模式,只有写入时,会有中断异常,异常处理函数为写进程复制一份新物理页,父子进程都拥有一块内容相同的物理页,异常函数返回,进程继续执行下去。
vfork
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
int count = 1;
int child;
if((child = vfork()) < 0){
perror("vfork failure ");
exit(1);
}else if((child=vfork()) == 0){
printf("This is child, count is: %d (%p). and his pid is: %d\n", ++count, &count, getpid());
exit(1);
}else {
printf("This is parent,count is: %d (%p), his pid is: %d\n", count, &count, getpid());
exit(1);
}
exit(0);
}
vfork创建出的子进程(线程)共享了父进程的count变量,2者的count指向了同一个内存,所以子进程修改了count变量,父进程的 count变量同样受到了影响。
1>vfork创造出来的子进程还会导致父进程挂起,除非子进程exit或者execve才会唤起父进程
2>vfok创建出来的子进程共享了父进程的所有内存,包括栈地址,直至子进程使用execv启动新的应用程序为止
3>由vfork创建出来得子进程不应该使用return返回调用者,或者使用exit()退出,但是它可以使用_exit()函数来退出
@vfork就是老小欺负老大,老小要吃雪糕,老大有,于是先吃老大的,等到父母执行exec买了新雪糕再把吃过的还给老大。记住exec不创建新进程,只是用新程序替换原正文、数据、堆栈,id不变。
clone
选择性的继承父进程的资源,你可以选择想vfork一样和父进程共享一个虚存空间,从而使创造的是线程,你也可以不和父进程共享,你甚至可以选择创造出来的进程和父进程不再是父子关系,而是兄弟关系。
来源网上程序:
#include <stdio.h>
#include <malloc.h>
#include <sched.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#define FIBER_STACK 8192
int a;
void * stack;
int do_something()
{
printf("This is son, the pid is:%d, the a is: %d\n", getpid(), ++a);
free(stack);
exit(1);
}
int main()
{
void * stack;
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 a is: %d\n", getpid(), a);
exit(1);
}
是创建一个线程(子进程共享了父进程虚存空间,没有自己独立的虚存空间不能称其为进程)。父进程被挂起当子线程释放虚存资源后再继续执行。