系统编程之进程的创建.僵尸与孤儿进程

 

一.进程

     

       进程是正在执行的程序实例。执行程序时,内核会将程序代码载入虚拟内存,为程序变量分配空间,在内核中建立相应的数据结构,以记录与进程有关的各种信息(比如,进程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\n", self_pid);
 12     printf("parent_pid = %d\n", 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\n");
 10     system("pwd");
 11     printf("Over\n");
 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\n");
 10     execlp("ls","ls","-l", (char *)0);
 11     printf("Over\n");
 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\n", getpid());
 24         printf("my parent process id:%d\n", 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\n", status>>8);
 34         printf("this is parent process:%d\n", getpid());
 35         printf("my parent process id:%d\n", 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\n", getpid());
 24         printf("my parent process id:%d\n", 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\n", status>>8);
 34         printf("this is parent process:%d\n", getpid());
 35         printf("my parent process id:%d\n", 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\n", getpid());
 24         printf("my parent process id:%d\n", 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\n", status>>8);
 34         printf("this is parent process:%d\n", getpid());
 35         printf("my parent process id:%d\n", getppid());
 36     }
 37     //父进程程序    
 38 
 39 
 40     return 7;
 41 }
~                                                                                                                                                                                  
~                

    运行结果:

    

    

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

 

    

      

 

 

    

posted @ 2015-06-02 20:50  慢伴拍的二叉树  阅读(325)  评论(0编辑  收藏  举报