函数名:fork
fork,创建一个子进程
包含文件:
#include <unistd.h>
函数原型:
pid_t fork(void);
返回值:
返回两次PID
成功,在父进程中返回子进程的PID(非负数),在子进程中返回0。
失败,父进程中返回-1,没有创建子进程。
实例:
int main()
{
int PID=0;
int fork_r=0;
PID=getpid();
printf("before fork pid=%d\n",PID);
fork_r=fork();
if(fork_r==-1){
printf("create fail\n");
}else{
printf("create success\n");
}
PID=getpid();
printf("the process pid=%d\n",PID);
if(fork_r!=0){
printf("this is the father process!\n");
}else{
printf("this is the child process!\n");
}
}
实验结果:
在fork()之前的语句只会被执行一次,fork()后的语句将会分别被子进程和父进程执行。
子进程拷贝了父进程什么内容?
简要概述:
早期的Unix内核:
把父进程的所有内容拷贝给子进程
Unix系统,用于实现一种傻瓜式的进程创建:当发出fork()系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程。
现在的Unix内核(包括Linux)
共享数据段,只有当子进程更改了数据段,才会拷贝一份数据段。
采用一种更为有效的方法称之为写时复制(或COW)。
这种思想相当简单:父进程和子进程共享页面而不是复制页面。然而,只要页面被共享,它们就不能被修改。
无论父进程和子进程何时试图写一个共享的页面,就产生一个错误,这时内核就把这个页复制到一个新的页面中并标记为可写。原来的页面仍然是写保护的:当其它进程试图写入时,内核检查写进程是否是这个页面的唯一属主;如果是,它把这个页面标记为对这个进程是可写的。
实例
int main()
{
int fork_r=0;
int a= 10;
fork_r=fork();
if(fork_r!=0){
printf("this is the father process!\n");
}else{
printf("this is the child process!\n");
a=a+10;
}
printf("a=%d\n",a);
}
fork创建一个子进程的目的
1、一个父进程希望复制自己,使父、子进程同时执行不同的代码段。
这在网络服务进程中是常见的——父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达。
实例:
可采用C语言模拟
int main()
{
int PID=0;
int fork_r=0;
int data =0;
while(1){
PID=getpid();
printf("before fork pid=%d\n",PID);
printf("please input a data:");
scanf("%d",&data);
if(data==1){
fork_r=fork();//新建一个子进程
if(fork_r!=0){
}else{
while(1){
PID=getpid();
printf("do some things, pid=%d\n",PID);
sleep(2);
}
}
}else{
printf("waitting...");
}
}
return 0;
}
2、一个进程要执行一个不同的程序。
这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec。