一、
Linux中使用fork函数创建一个进程:
pid_t fork(void);
fork函数调用成功,返回两次
返回值为0,代表当前进程为子进程
返回值为非负数,代表当前进程为父进程
调用失败,则返回-1
二、代码演示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = getpid();
fork();
printf("my pid is %d, current pro id: %d\n",pid,getpid());
return 0;
}
上述代码结果为
fork之后printf会被调用两次,两次打印了进程id号,出现了一个新进程。
新进程只执行fork之后的代码。
include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid_t pid2;
pid = getpid();
printf("before fork:pid = %d\n",pid);
fork();
pid2 = getpid();
printf("after fork:pid = %d\n",pid2);
if(pid == pid2){
printf("this is father print\n");
}else{
printf("this is child print,child pid = %d\n",getpid());
}
return 0;
}
结果为:
fork调用返回两次,第一次返回值时,pid2的值和pid相等,则执行if里面的语句,此时是父进程,第二次返回时pid2与pid不相等,所以执行else里面的语句,为子进程。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
printf("father: id = %d\n",getpid());
pid = fork();
if(pid > 0)
{
printf("this is father print,pid = %d\n",getpid());
printf("pid = %d\n",pid);
}
else if(pid == 0)
{
printf("this is child print,child pid = %d\n",getpid());
}
return 0;
}
结果为:
结果可以看出,在父进程中,fork返回的是非负数,并且是子进程的pid号,子进程的为0。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int data = 10;
printf("father: id = %d\n",getpid());
pid = fork();
if(pid > 0)
{
printf("this is father print,pid = %d\n",getpid());
}
else if(pid == 0)
{
printf("this is child print,child pid = %d\n",getpid());
data = data+10;
}
printf("data = %d\n",data);
return 0;
}
结果为:
父子进程的拷贝属于全拷贝,包括数据段,栈,堆,正文,IO等。
fork创建子进程的目的:
1.一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的--父进程等待客户端服务请求。当这种请求到达时,父进程调用fork,使子进程处理次请求。父进程则继续等待下一个服务请求到达。
2.一个进程要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec。
例子:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int data = 10;
while(1){
printf("please input a data\n");
scanf("%d",&data);
if(data == 1){
pid = fork();
if(pid > 0)
{
}
else if(pid == 0)
{
while(1){
printf("do net request,pid = %d\n",getpid());
sleep(1);
}
}
}
else
{
printf("wait,:do nothing\n");
}
}
return 0;
}
三、vfork函数也可以创建进程,与fork有什么区别
关键区别一:vfork直接使用父进程存储空间,不拷贝。
关键区别二:vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = vfork();
if(pid > 0)
{
while(1){
printf("this is father print,pid = %d\n",getpid());
sleep(1);
printf("cnt = %d\n",cnt);
}
}
else if(pid == 0)
{
while(1){
printf("this is child print,child pid = %d\n",getpid());
sleep(1);
cnt++;
if(cnt == 3){
exit(0);
//_exit(0);
//_Exit(0);
}
}
}
return 0;
}
结果为:
子进程执行三次,exit退出后父进程执行。