今天学Solaris的进程模型,突然看到了其中关于fork()与vfork()两个函数的程序,通过这个程序,加深了对创建进程的认识。程序如下:
#include
#include
#include
#include
globa=6;
int main(void)
{
var=88;
pid_t result;
result = fork();
//result = vfork();
if(result == -1)
{
perror("fork");
exit;
}
else if(result == 0)
{
globa++;
var++;
printf("The return value is %d\n In child process!!\n My PID is %d\n",result,getpid());
}
else
{
printf("The return value is %d\n In father process!!\n My PID is %d\n",result,getpid());
}
printf("PID=%d,globa=%d,var=%d",getpid(),globa,var);
}
程序运行结果如下:
(fork()运行结果)
The return value is 0
In child process!!
My PID is 3736
PID=3736,globa=7,var=89
The return value is 3736
In father process!!
My PID is 3735
PID=3735,globa=6,var=88
(vfork()运行结果)
The return value is 0
In child process!!
My PID is 3736
PID=3736,globa=7,var=89
The return value is 3736
In father process!!
My PID is 3735
PID=3735,globa=7,var=89
分析:首先分析fork与vfork函数的运行机制,拿fork为例,fork()并不是进程切换,而是复制一个当前进程。当使用pid=fork()时,其实是创建了两个进程,这两个进程有着相同的内容,例如变量的值,空间配,特别是正在执行的语句等等都相同,但这些内容却在两个独立的内存空间中。因此当执行上述代码时,便相当于同一段代码在两个进程中执行,所有就出现了两个结果,一个是子进程的信息,一个是父进程的信息。再看globa和var这两个变量,由于是两个独立的进程,因此当各自执行代码时,变量也不会互相受到影响,所以在子进程中的globa和var均发生了变化,而在父进程中却没有变化。
其次分析一下,fork()和vfork()的区别:vfork采用写时拷贝技术(write-on-copy),父进程与子进程享用同一个内存空间,因此,程序中的变量其实也就是父子进程的公共变量,所以,当其中一个进程中的变量值发生改变时,另一个进程中的变量值肯定也跟着发生变化,另外,两个函数的区别还在于vfork用于创建一个新进程,而该新进程的目的是exec一个新进程,vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec,于是也就不会存放该地址空间。不过在子进程中调用exec或exit之前,他在父进程的空间中运行。vfork保证子进程先运行,在她调用exec exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。 用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序,当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执行,因为调用exec并不创建新进程,所以前后的进程id 并未改变,exec只是用另一个新程序替换了当前进程的正文,数据,堆和栈段。
阅读(1658) | 评论(0) | 转发(1) |