一、例程说明
1、调用fork()创建进程,分析创建进程的过程和fork()的返回值变化
2、调用vfork()创建进程,比较与fork函数的区别
2、验证fork()与vfork(),父进程和子进程所占用的存储空间是否共享
二、fork()例程代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
int g =0;
int main(int argc, char*argv[])
{
pid_t ret_pid; //定义pid返回值
int a =0; //定义局部变量
if((ret_pid = fork()) < 0) //调用fork函数创建子进程
{
perror("fork failed.why:");
}
else if(ret_pid > 0)
{
printf("this is farther progress(farther current pid = %d ), ret_pid = %d\r\n", getpid(),ret_pid);
a+=10; //父进程改变局部变量
g += 10; //父进程改变全局变量
}
else if(ret_pid == 0)
{
printf("this is childr progress(child current pid = %d ), ret_pid = %d\r\n", getpid(),ret_pid);
a+=20; //子进程改变局局变量
g+=20; //子进程改变全局变量
}
printf("a = %d\r\n", a);
printf("g = %d\r\n", g);
exit(0); //等价于return(0),exit函数对所有打开流调用fclose函数,清洗缓冲,终止进程
}
例程执行结果与分析
this is farther progress(farther current pid = 28942 ), ret_pid = 28943
a = 10
g = 10
this is childr progress(child current pid = 28943 ), ret_pid = 0
a = 20
g = 20
1)根据结果中父进程和子进程的全局与局部变量的值,可知父进程与子进程对全局、局部变量的改变互不影响,即子进程只是父进程数据空间、堆栈空间的副本,并不共享这些存储空间,仅共享正文段。
2)根据结果中的fork函数返回值ret_pid可知,在父进程中,fork返回值ret_pid为28943(非负整数)作为了子进程的ID;在子进程中,fork返回值ret_pid返回值为0。即调用fork函数,一次执行,两次返回。
3)经过多次执行,父进程和子进程谁先执行并不确定(可用sleep()函数来控制执行的先后。)
三、vfork()例程代码
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
int global_val = 0;
int main(void)
{
int a = 0;
pid_t pid;
if((pid = vfork()) < 0)
{
perror("vfork failed,why:");
}
else if(pid > 0)
{
printf("this is farther progress(farther pid = %d ), pid = %d\r\n", getpid(), pid);
global_val+=10;
a+=10;
}
else if(pid == 0)
{
printf("this is child progress(child pid = %d), pid = %d\r\n", getpid(),pid);
global_val+=20;
a+=20;
// _exit(0);//如果子进程调用_exit,即终止了子进程,之后将不再执行后面的语句
}
printf("global_val = %d\r\n", global_val);
printf("a = %d\r\n", a);
exit(0);
}
例程执行结果
this is child progress(child pid = 31252), ret_pid = 0
global_val = 20
a = 20
this is farther progress(farther pid = 31251 ), ret_pid = 31252
global_val = 30
a = 30
1)根据结果中父进程和子进程的全局与局部变量的值,可知父进程与子进程对全局、局部变量的改变是相互影响的,即父进程与子进程共享地址空间。
2)根据结果中的vfork()函数返回值ret_pid可知,在父进程中,fork()返回值ret_pid为28943(非负整数)作为了子进程的ID;在子进程中,fork()返回值ret_pid返回值为0。即调用fork()函数,一次执行,两次返回(这与fork()函数是相同的)。
3)经过多次执行,由vfork()创建的子进程,父进程总是会等待子进程执行完毕(内核会将父进程处于休眠状态),才可能调度运行。
4)在子进程中如果未调用exit或者exec,父进程可能将会处于阻塞的状态。