fork()和vfork()

查看系统中正在运行的进程的信息:
ps -aux
进程状态:
fork()和vfork()_第1张图片

fork()和vfork()_第2张图片

进程创建:

一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

1.fork()函数:

/* 
 *  fork_test.c 
 *  version 1 
 *  Created on: 2010-5-29 
 *      Author: wangth 
 */  
#include   
#include    
int main ()   
{   
    pid_t fpid; //fpid表示fork函数返回的值  
    int count=0;  
    fpid=fork();   
    if (fpid < 0)   
        printf("error in fork!");   
    else if (fpid == 0) {  
        printf("i am the child process, my process id is %d/n",getpid());   
        printf("我是爹的儿子/n");//对某些人来说中文看着更直白。  
        count++;  
    }  
    else {  
        printf("i am the parent process, my process id is %d/n",getpid());   
        printf("我是孩子他爹/n");  
        count++;  
    }  
    printf("统计结果是: %d/n",count);  
    return 0;  
}  

运行结果是:
i am the child process, my process id is 5574
我是爹的儿子
统计结果是: 1
i am the parent process, my process id is 5573
我是孩子他爹
统计结果是: 1

/* 
 *  fork_test.c 
 *  version 2 
 *  Created on: 2010-5-29 
 *      Author: wangth 
 */  
#include   
#include   
int main(void)  
{  
   int i=0;  
   printf("i son/pa ppid pid  fpid/n");  
   //ppid指当前进程的父进程pid  
   //pid指当前进程的pid,  
   //fpid指fork返回给当前进程的值  
   for(i=0;i<2;i++){  
       pid_t fpid=fork();  
       if(fpid==0)  
           printf("%d child  %4d %4d %4d/n",i,getppid(),getpid(),fpid);  
       else  
           printf("%d parent %4d %4d %4d/n",i,getppid(),getpid(),fpid);  
   }  
   return 0;  
}  

运行结果是:
i son/pa ppid pid fpid
0 parent 2043 3224 3225
0 child 3224 3225 0
1 parent 2043 3224 3226
1 parent 3224 3225 3227
1 child 1 3227 0
1 child 1 3226 0

fork()和vfork()_第3张图片

/* 
 *  fork_test.c 
 *  version 4 
 *  Created on: 2010-5-29 
 *      Author: wangth 
 */  
#include   
#include   
int main() {  
    pid_t fpid;//fpid表示fork函数返回的值  
    //printf("fork!");  
    printf("fork!/n");  
    fpid = fork();  
    if (fpid < 0)  
        printf("error in fork!");  
    else if (fpid == 0)  
        printf("I am the child process, my process id is %d/n", getpid());  
    else  
        printf("I am the parent process, my process id is %d/n", getpid());  
    return 0;  
}  

执行结果如下:
fork!
I am the parent process, my process id is 3361
I am the child process, my process id is 3362
如果把语句printf(“fork!/n”);注释掉,执行printf(“fork!”);
则新的程序的执行结果是:
fork!I am the parent process, my process id is 3298
fork!I am the child process, my process id is 3299
程序的唯一的区别就在于一个/n回车符号,为什么结果会相差这么大呢?
这就跟printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上。但是,只要看到有/n 则会立即刷新stdout,因此就马上能够打印了。
运行了printf(“fork!”)后,“fork!”仅仅被放到了缓冲里,程序运行到fork时缓冲里面的“fork!” 被子进程复制过去了。因此在子进程度stdout缓冲里面就也有了fork! 。所以,你最终看到的会是fork! 被printf了2次!!!!
而运行printf(“fork! /n”)后,“fork!”被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有fork! 内容。因此你看到的结果会是fork! 被printf了1次!!!!
所以说printf("+");不能正确地反应进程的数量。

难点:

#include   
#include   
int main(int argc, char* argv[])  
{  
   fork();  
   fork() && fork() || fork();  
   fork();  
   return 0;  
}  

问题是不算main这个进程自身,程序到底创建了多少个进程。
答案是总共20个进程,除去main进程,还有19个进程。

第一个fork和最后一个fork肯定是会执行的。
主要在中间3个fork上,可以画一个图进行描述。
这里就需要注意&&和||运算符。
A&&B,如果A=0,就没有必要继续执行&&B了;A非0,就需要继续执行&&B。
A||B,如果A非0,就没有必要继续执行||B了,A=0,就需要继续执行||B。
fork()对于父进程和子进程的返回值是不同的,按照上面的A&&B和A||B的分支进行画图,可以得出5个分支。
加上前面的fork和最后的fork,总共4*5=20个进程,除去main主进程,就是19个进程了。
fork()和vfork()_第4张图片

2.vfork():

fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别:

  1. fork ():子进程拷贝父进程的数据段,代码段
    vfork ( ):子进程与父进程共享数据段
  2. fork ()父子进程的执行次序不确定
    vfork 保证子进程先运行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec
    或exit 之后父进程才可能被调度运行。
  3. vfork ()保证子进程先运行,在她调用exec 或exit 之后父进程才可能被调度运行。如果在
    调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

你可能感兴趣的:(Linux)