全部博文(842)
分类: LINUX
2012-03-04 17:32:59
进程控制fork函数和vfork函数
1.1 函数原型:
头文件:
pid_t getpid(void); //返回调用进程的进程ID
pid_t getppid(void); //返回进程的父进程ID
uid_t getuid(void); //返回调用进程的实际用户ID
uid_t geteuid(void); //返回调用进程的有效用户ID
gid_t getgid(void); //返回调用进程的实际组ID
gid_t getegid(void); //返回调用进程的有效组ID
1.2 fork函数
1. 函数原型:
pid fork(void);
头文件:
返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1。
函数功能:创建一个新进程。
2.示例:
************************ 例 8-1 ****************************
//使用fork函数创建子进程
#include "apue.h"
int glob = 6;
char buf[] = "a write to stdout\n";
int
main(void)
{
int var;
pid_t pid;
var = 88;
if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != (sizeof(buf)-1))
printf("write error\n");
printf("before fork\n");
fflush(NULL);//注意
if((pid = fork()) < 0)
{
printf("fork error\n");
}
else if(pid == 0)
{
printf("son :\n");
glob++;
var++;
}
else
{
printf("parent :\n");
sleep(2);
}
printf("pid = %d, var = %d, glob = %d\n", getpid(), var, glob);
return 0;
}
如果输出到终端设备时是行缓冲的,输出了printf("before fork\n");后数据还在缓冲区里面,在终端下面只能看见一次,而如果重定向到文件时,则变成了全缓冲的,父进程创建子进程时,其缓冲区也复制给了子进程在调用exit之后会刷新缓冲区,所以出现了两个before fork,如果在创建子进程之前刷新缓冲区fflush(NULL),就不会出现这种状况了。
*******************************************************
例程2:
#include "apue.h"
int glob;
int
main(void)
{
int var;
pid_t pid;
printf("before fork \n");
if((pid = fork()) < 0)
{
printf("fork error");
}
else if(pid == 0)
{
var = 1;
glob = 2;
printf("son : var = %d, glob = %d\n", var, glob);
}
else
{
var = 3;
glob = 4;
printf("parent : var = %d, glob = %d\n", var, glob);
}
printf("test \n");
return 0;
}
结果:
before fork
son : var = 1, glob = 2
test
parent : var = 3, glob = 4
test
从结果可以看出子进程是不影响父进程变量的值的,并且父子进程都要执行以后的程序段,这就可能形成竞争,以后会提到解决的方法。
1.3 vfork函数
1. vfork函数用于创建一个新进程,而该新进程的目的是exec一个新程序。
2. vfork函数与fork函数的区别:
都一个样创建子进程,但是vfork并不将父进程的地址空间完全复制到子进程中,相反,在子进程调用exec或exit之前,它在父进程
空间运行。还有,vfork保证子进程运行,在它调用exec或exit之后父进程才能被调度运行。
例程3:
#include "apue.h"
int glob = 6;
char buf[] = "a write to stdout\n";
int
main(void)
{
int var;
pid_t pid;
var = 88;
if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != (sizeof(buf)-1))
printf("write error\n");
printf("before vfork\n");
if((pid = vfork()) < 0)
{
printf("vfork error\n");
}
else if(pid == 0)
{
glob++;
var++;
_exit(0);
}
else
{
sleep(2);
}
printf("pid = %d, var = %d, glob = %d\n", getpid(), var, glob);
return 0;
}
结果:
a write to stdout
before vfork
pid = 3755, var = 89, glob = 7
从这里可以看出来,在子进程调用exec或exit之前,它在父进程里面,所以该边了父进程变量的值。