进程控制_1_进程创建

    进程创建就是一个进程向内核申请一个新进程来运行部分代码,原进程就称为父进程,新进程就称为子进程。创建成功后,子进程的代码与父拥有相同的代码,并且都运行到同一位置,接下来分别完成各自的代码。父进程调用 fork 函数来创建子进程,父进程调用 fork 后,内核就分配新的内存空间和内核数据结构给子进程,并且将父进程部分数据结构拷贝给子进程,再将子进程加入到系统进程列表中,最后 fork 返回,调度器开始调度。
     

1.fork 函数       
#include <unistd.h>   // 头文件
pid_t fork(void);

// 返回值 子进程返回 0,父进程返回子进程 id, 出错返回 -1
// pid_t 是一个类似整型的类型
// 子进程拷贝了父进程的代码,所以会有两个返回值
// 调用失败的原因可能是系统中进程过多,或者用户的进程数超过了限制


    
    下面是一个例子,子进程只执行 fork 之后的代码:
  1 #include <stdio.h>                                                                                                                
  2 #include <stdlib.h>                                                                                                               
  3 #include <unistd.h>                                                                                                               
  4                                                                                                                                   
  5 int main()                                                                                                                        
  6 {                                                                                                                                 
  7     pid_t pid;                                                                                                                    
  8     printf("before: pid is %d\n", getpid());                                                                                      
  9     pid = fork();                                                                                                                 
10     if(pid < 0){                                                                                                                  
11         printf("fork error.\n");                                                                                                  
12     }                                                                                                                             
13     printf("after: pid is %d\n", getpid());                                                                                       
14     sleep(1);                                                                                                                     
15     return 0;                                                                                                                     
16 }
    
    子进程只执行 fork 之后的代码

2.写时拷贝
    父进程创建子进程后,父子代码数据共享,这里采用的拷贝的方式是写时拷贝,就是先以浅拷贝的方式将父进程的所有代码与数据拷贝给子进程,当任意一方需要写入的数据时,采用深拷贝的方式将要修改的部分拷贝给子进程。父进程的代码与数据完整拷贝给子进程是需要较长时间的,而创建子进程很快,所以只是将父进程的内存地址保存给子进程,实质上就是与父进程看到同一份资源,当需要修改时,重新开辟内存,将要修改的部分拷贝给子进程。

3.vfork 函数
    fork 函数创建子进程时,父子进程拥有各自独立的地址空间,数据不会互相影响,父子进程谁先被调度也是不确定的,要想保证子进程优先被调度,有 vfork 函数,vfork 函数也是用来创建子进程的,保证子进程先执行,只有子进程退出后,父进程才能继续执行,但是它创建的子进程和父进程共享地址空间,数据会互相影响。
    以下为举例说明 fork 和 vfork:
    (1)fork
27 int main()   // fork                                                                                                              
28 {                                                                                                                                 
29     int num = 0;                                                                                                                  
30     pid_t pid = fork();                                                                                                           
31     if(pid < 0){                                                                                                                  
32         printf("fork error.\n");                                                                                                  
33     }else if(pid == 0){                                                                                                           
34         // child                                                                                                                  
35         num = 1;                                                                                                                  
36         printf("i am child, pid is %d, num is %d\n", getpid(), num);                                                              
37     }else{                                                                                                                        
38         // father                                                                                                                 
39         printf("i am father, pid is %d, num is %d\n", getpid(), num);                                                             
40         sleep(1);                                                                                                                 
41     }                                                                                                                             
42     return 0;                                                                                                                     
43 }
    
    子进程修改 num 数值,并未影响父进程的 num 的值

    (2)vfork
  6 int main()    // vfork                                                                                                            
  7 {                                                                                                                                 
  8     int num = 0;                                                                                                                  
  9     pid_t pid = vfork();                                                                                                          
10     if(pid < 0){                                                                                                                  
11         printf("fork error.\n");                                                                                                  
12     }else if(pid == 0){                                                                                                           
13         // child                                                                                                                  
14         num = 1;                                                                                                                  
15         printf("i am child, pid is %d, num is %d\n", getpid(), num);                                                              
16         exit(0);                                                                                                                  
17     }else{                                                                                                                        
18         // father                                                                                                                 
19         printf("i am father, pid is %d, num is %d\n", getpid(), num);                                                             
20         sleep(1);                                                                                                                 
21     }                                                                                                                             
22     return 0;                                                                                                                     
23 }

    子进程修改了 num 数值,父进程的 num 也改变了,父子进程公用内存空间










猜你喜欢

转载自blog.csdn.net/Cherubim1/article/details/80338274