fork
fork()通过复制调用进程来创建一个新进程。新进程被称为子进程;调用进程被称为父进程。
特点:
1.子进程和父进程在不同的内存空间中运行
2.在fork()的时候,这两个内存空间有相同的特性内容,两个进程将执行fork()系统调用之后的下一条指令,子进程使用相同的CPU寄存器值。
3.其中一个进程执行的内存写、文件映射和反映射不会影响另一个进程。
返回值说明:
fork成功后,子进程的PID在父进程中返回,在子进程中返回0。失败则返回返回-1,父进程不创建子进程。
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("fork error");
}
else if(pid == 0)
{
printf("child pid = %d\n",getpid());
}
else{
printf("parent pid = %d\n",getpid());
}
while(1)
sleep(1);
return 0;
}
结果:
xl@xl-VirtualBox:/media/sf_1/demo/fork$ ./fork
parent pid = 2947
child pid = 2948
vfork
vfork()也是创建一个子进程。vfork()函数与fork()具有相同的效果。
不同点 :
-
fork : 子进程会拷贝父进程数据段
-
vfork : 子进程与父进程共享数据段
-
fork : 子进程创建以后,父子进程执行顺序与系统调度算法有关,不确定
-
vfork : 子进程创建以后,子进程先运行,父进程后运行
注意事项
在Linux下,fork()是使用写时复制页面实现的,因此fork()带来的唯一损失就是时间和内存需要复制父进程的页表,并为子进程创建唯一的任务结构。
然而,以前一次fork()需要对调用者的数据空间做一个完整的副本,这通常是不必要的,为了提高效率引入了vfork()系统调用,该调用没有完全复制地址空间,但借用父进程的内存和控制线程,直到发生execve()调用或退出。
注意不能使用vfork以后在main中使用return,因为函数栈父子进程共享,如果一方直接return了,意味着函数栈释放,从而导致程序运行错误,下面的实验你如果把fork的程序直接修改为vfork会导致程序运行完子进程在运行父进程就会错误,而必须在子进程中调用_exit(0);使得子进程退出,父进程执行。