您的位置:首页 > 其它

僵尸进程和孤儿进程

2017-04-15 22:21 323 查看
        当进程创建时他会被载进虚拟内存,为程序变量分配空间,并把相关信息添到task_struck里。

进程内存分布分为4个不同的阶段:

1、文本段,包含程序的源指令。

2、数据段,包含了静态变量。

3、堆、动态内存分区区域。

4、栈、动态增长与收缩的段,保存本地变量。

      这里有两种创建进程的方法、fork()和execve()。它们都是系统调用,但他们的运行方式有点不同。

      要创建一个子进程可以执行fork()系统调用。然后子进程得到父进程中数据段、栈段和堆区域的一份拷贝。子进程可以独立修改这些内存段。但是文本段是父进程和子进程共享的内存段,不能被子进程修改。

      如果使用execve()创建一个新进程。这个系统调用会销毁所有的内存段去重建一个新的内存段。然而,exevce()需要一个可执行文件或者脚本作为参数,这和fork()与所不同。

注意,execve()和fork()创建的进程都是运行进程的子进程。

       进程执行还有许多其他的内容,比如进程调度、权限许可、资源限制、库链接,内存映射。

       下面有两个比较特殊的进程:

       僵尸进程:一个子进程在其父子进程没有调用wait()和waitpid()的情况下退出。这个子进程就叫做僵尸进程。如果其父进程还存在而一直不调用wait,则该僵尸进程无法回收,等到其父进程退出后该进程将被init回收。

         代码:

  1 #include<stdio.h>

  2 #include<unistd.h>

  3 #include<errno.h>

  4 #include<stdlib.h>

  5 int main()

  6 {

  7     pid_t pid =getpid();

  8     pid_t id=fork();

  9     if(-1==id)

 10     {

 11         printf("fork error!return code is:%d\n",errno);

 12         return 2;

 13     }

 14     else if(0==id)

 15     {

 16         printf("Child pid is:%d\n",getpid());

 17         exit(3);

 18     }

 19     else

 20     {

 21         printf("Father pid is:%d,return pid is:%d\n",getpid(),id);

 22         sleep(3);

 23     }

       运行结果如下:

        


       僵尸进程的危害:unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息,就可以得到。这种机制就是:在每个进程退出时,内核释放该进程所有的资

源,包括打开的文件,占有的内存等。但是任然为其保留一定的信息(包括进程号the process ID,退出状态
the termimation status of the process,运行时间

amount of CPU time taken by the process等)。直到父进程通过wait/waitpid来取时才释放。但如果进程不调用wait/waitpid的话,保留的那段信息就不会释放,

其进程信号就会一直被占用,然而系统的进程信号是有限的,如多大量的产生僵死进程,最终会因为没有可用的进程信号而导致系统不能产生新的进程,这是僵尸进

程的危害,最好避免。

     僵尸进程的解决方法:

    (1)通过信号机制

      子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。

    (2)fork()两次

      原理是将子进程成为孤儿进程,从而父进程变为init进程,通过init进程可以处理僵尸进程。

    孤儿进程:一个父进程退出,而他的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: