fork()函数
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t fork(void);
函数参数:
无
函数功能:
创建子进程
返回值:
父进程:返回子进程的pid
子进程:返回0
错误:-1,并且使用perror查看错误信息
代码实现
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid=fork();//子进程开始
if(pid==-1)
{
perror("fork");
return -1;
}
if(pid==0)//子进程
{
printf("child pid:%d parent pid:%d\n",getpid(),getppid());//打印子进程的pid和子进程的父进程的pid
exit(0);//结束子进程
}
else
{
//sleep(1);
wait(NULL);//等待子进程结束
printf("parent pid:%d parent pid:%d\n",getpid(),getppid());//打印父进程pid,和父进程的父进程的pid
exit(0);
}
return 0;
}
运行结果
可以看出子进程与父进程的pid是不一样的。而且父进程与子进程运行顺序不是固定的。要想子进程先运行,则必须让父进程等待子进程运行结束。
fork函数特点
fork函数所创建的子进程是父进程的完整副本,复制了父进程的资源,包括内存的task_struct内容。子进程拥有自己的虚拟地址空间,父子进程数据独有,(写时复制)代码共享。fork函数的返回值起到分流的作用,可以用fork的返回值判断哪个是父进程或子进程。
vfork()函数
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t vfork(void);
函数参数:
无
函数功能:
创建子进程
返回值:
父进程:返回子进程的pid
子进程:返回0
错误:-1,并且使用perror查看错误信息
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t pid ;
pid = vfork();
if(pid==-1)
{
perror("vfork");
return -1;
}
else if(pid == 0)
{
printf("this is child, pid=%d parent pid=%d\n",getpid(),getppid());
exit(0);
}
else
{
//wait(NULL);
printf("this is father,pid=%d\n",getpid());
}
return 0;
}
运行结果
可以看出vfork与fork代码差不多,只不过vfork是让子进程优先运行。
vfork函数特点
vfork函数子进程的虚拟地址是直接共享父进程的,从而物理地址也就被理所当然的共享了父进程会保证子进程先运行,在子进程调用exit后才可能被调度运行。
fork与vfork比较
fork复制父进程的页表项,当进行写操作时,内核会给子进程分配一个新的物理页面;而vfork与父进程共用页表项,当写操作时,是直接写在父进程的物理页面。