zoukankan      html  css  js  c++  java
  • 系统编程之进程的创建.僵尸与孤儿进程

     

    一.进程

         

           进程是正在执行的程序实例。执行程序时,内核会将程序代码载入虚拟内存,为程序变量分配空间,在内核中建立相应的数据结构,以记录与进程有关的各种信息(比如,进程ID、用户ID、组ID以及终止状态等)

              在内核看来,进程是一个个实体,内核必须在它们之间共享各种计算机资源。对于像内存这样的受限资源来说,内核一开始会为进程分配一定数量的资源,并 在进程的生命周期内,统筹该进程和整个系统对资源的需求,对这一分配进行调整。程序终止时,内核会释放所有此类资源,供其他进程重新使用。其他资源(如 CPU、网络带宽等)等属于可再生资源,但必须在所有进程间平等共享。

       我们可以通过ps -aux来打印当前的所有进程,其中状态具体表示为:S表示睡眠,R表示可运行,D表示等待,T表示停止,Z表示死进程或僵尸进程,PID表示进程号,PPID表示父进程号。接下来打印当前程序的进程号和父进程号:

        

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 
      5 //typedef unigned int pid_t
      6 int main(void)
      7 {
      8     pid_t self_pid =  getpid();
      9     pid_t parent_pid = getppid();
     10 
     11     printf("self_pid = %d
    ", self_pid);
     12     printf("parent_pid = %d
    ", parent_pid);//bash
     13 
     14     return 0;
     15 }
    ~                                                                                    
    ~                                                                                    
    ~             

      二:创建新进程:

        创建一个新的进程可以分为三种方法:systeme(),exel()族,fork();

        1,system()

          system()函数调用“/bin/sh -c command”执行特定的命令,阻塞当前进程直到command命令执行完毕

            以下是通过system来打印当前的路径:

          

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 
      6 //typedef unigned int pid_t
      7 int main(void)
      8 {
      9     printf("execute this command
    ");
     10     system("pwd");
     11     printf("Over
    ");
     12 
     13 
     14     return 0;
     15 }
    ~                                                                                    
    ~                                                                                    
    ~                                                                                    
    ~    

        运行结果:

          

      

        2.exel族(execl、execlp、execle、execv、execvp)

        execl系列函数是替换类创建进程,即在创建进程的同时,把以前的进程干掉,其具体的原型为:

      

              原型:

            int execl(const char *path, const char *arg, ...);

            int execlp(const char *file, const char *arg, ...);

            int execle(const char *path, const char *arg, ..., char * const envp[]);

            int execv(const char *path, char *const argv[]);

          以下是 execl创建进程:

          

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 
      6 //typedef unigned int pid_t
      7 int main(void)
      8 {
      9     printf("execute this command
    ");
     10     execlp("ls","ls","-l", (char *)0);
     11     printf("Over
    ");
     12 
     13 
     14     return 0;
     15 }

          运行结果:

        

        可以发现,以前应该打印的over那句,没有打印,这就是因为被他的子进程干掉了。

        3.fork孤儿进程

        在fork函数之前,需要了解两个概念:第一个是孤儿进程:就是一个进程的父进程比子进程先要退出,

        以下是一个孤儿进程的实例:

        

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 
      6 //fork---->孤儿进程,僵尸进程,
      7 
      8 int main(void)
      9 {
     10     pid_t pd = 0;
     11     int status = 0;
     12 
     13     pd = fork();
     14 
     15     if(0 > pd)
     16     {
     17         perror("fork");
     18         exit(EXIT_FAILURE);//--->return 
     19     }
     20 
     21     if(0 == pd)
     22     {
     23         printf("this is child process:%d
    ", getpid());
     24         printf("my parent process id:%d
    ", getppid());
     25         //sleep(5);
     26         exit(9);
     27     }
     28     //子进程程序
     29     else if(0 < pd)
     30     //pd > 0
     31     {
     32         //  wait(&status);//回收子进程资源
     33         //printf("status is %d
    ", status>>8);
     34         printf("this is parent process:%d
    ", getpid());
     35         printf("my parent process id:%d
    ", getppid());
     36         //sleep(1);
     37     }
     38     //父进程程序    
     39 
     40 
     41     return 7;
     42 }

        

        运行结果:

        

             可以看到首先打印的是父进程,在打印的是子进程,子进程的父进程号为 1,1是init进程,也是所有进程的祖先进程。

        当一个进程成了孤儿进程之后,都会有init进程来回收所有的资源,所以说,孤儿进程的资源不会存在浪费。

        4.fork僵尸进程

         当一个进程结束,而父进程却没有调用wait函数来回收进程的资源。这个进程叫做僵尸进程.

         以下是一个僵尸进程的实例,让父进程睡秒之后再退出!

          

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 
      6 //fork---->孤儿进程,僵尸进程,
      7 
      8 int main(void)
      9 {
     10     pid_t pd = 0;
     11     int status = 0;
     12 
     13     pd = fork();
     14 
     15     if(0 > pd)
     16     {
     17         perror("fork");
     18         exit(EXIT_FAILURE);//--->return 
     19     }
     20 
     21     if(0 == pd)
     22     {
     23         printf("this is child process:%d
    ", getpid());
     24         printf("my parent process id:%d
    ", getppid());
     25         //sleep(5);
     26         exit(9);
     27     }
     28     //子进程程序
     29     else if(0 < pd)
     30     //pd > 0
     31     {
     32         //wait(&status);//回收子进程资源
     33         //printf("status is %d
    ", status>>8);
     34         printf("this is parent process:%d
    ", getpid());
     35         printf("my parent process id:%d
    ", getppid());
     36         sleep(5);
     37     }
     38     //父进程程序    
     39 
     40 
     41     return 7;
     42 }
    ~             

        运行结果:

        

        在父进程睡的这5S中可以看到26977的状态为僵尸态。

         为了避免这种僵尸状态的出现,造成资源的浪费,需要对子进程的进行“收尸”

        一般父进程需要调用wait函数来等待子进程退出之后再退出。

        接下来是一个正常退出的进程:

        

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 
      6 //fork---->孤儿进程,僵尸进程,
      7 
      8 int main(void)
      9 {
     10     pid_t pd = 0;
     11     int status = 0;
     12 
     13     pd = fork();
     14 
     15     if(0 > pd)
     16     {
     17         perror("fork");
     18         exit(EXIT_FAILURE);//--->return 
     19     }
     20 
     21     if(0 == pd)
     22     {
     23         printf("this is child process:%d
    ", getpid());
     24         printf("my parent process id:%d
    ", getppid());
     25         sleep(5);
     26         exit(9);
     27     }
     28     //子进程程序
     29     else if(0 < pd)
     30     //pd > 0
     31     {
     32         wait(&status);//回收子进程资源
     33         printf("status is %d
    ", status>>8);
     34         printf("this is parent process:%d
    ", getpid());
     35         printf("my parent process id:%d
    ", getppid());
     36     }
     37     //父进程程序    
     38 
     39 
     40     return 7;
     41 }
    ~                                                                                                                                                                                  
    ~                

        运行结果:

        

        

        可以看到父进程在5S之后等待子进程退出之后在退出!回收子进程的资源!

        

          

     

        

  • 相关阅读:
    题解 P4111 [HEOI2015]小 Z 的房间
    题解 P3317 [SDOI2014]重建
    题解 P4336 [SHOI2016]黑暗前的幻想乡
    NOIP 模拟 7 考试总结
    NOIP 模拟 7 回家
    NOIP 模拟 7 寿司
    MySQL: 多表查询
    MySQL:设计演员与角色表(多对多)
    MySQL:设计省&市表 (一对多)
    MySQL:多表关系设计(一对多 / 多对多 / 一对一)
  • 原文地址:https://www.cnblogs.com/hongzhunzhun/p/4547618.html
Copyright © 2011-2022 走看看