Linux(Android NDK)如何避免僵死进程

来源:互联网 发布:船舶数据库 编辑:程序博客网 时间:2024/05/15 11:55

     服务器程序一般功能可概括为:初始化资源;等待客户端的连接;创建一个进程处理客户端请求。Linux(Android NDK)中创建多进程序程序是非常简单的。但是稍微不注意,就会出现僵死进程,造成的主要危害有:系统的进程号是有限的,僵死进程始终占用进程号,有进程号耗尽之忧;僵死进程仍然消耗销量的系统资源,造成资源浪费;如果是服务器程序,长时间运行后,产生了成千上万的僵死进程,在客户和主管面前情何以堪呢。所以僵死进程一定要避免。

   先看现象吧,打开Linux命令行终端,输入ps,看看僵死进程的样子吧。IPTV_Server内部创建了3个进程,多次运行后产生了5个僵死进程(父进程号为328;僵死标志位Z)。

root      320   319   11236  3840  ffffffff 4015576c S /system/bin/iptv_serverroot      328   320   11136  1784  c06a0f0c 40155a70 S /system/bin/iptv_serverroot      901   328   11164  2044  c063af54 40154d50 S /system/bin/iptv_serverroot      902   901   15948  2968  ffffffff 40154d50 S /system/bin/iptv_serverroot      399   328   0      0     c056360a 00000000 Z iptv_serverroot      405   328   0      0     c085982e 00000000 Z iptv_serverroot      423   328   0      0     c0322437 00000000 Z iptv_serverroot      455   328   0      0     c0368148 00000000 Z iptv_serverroot      652   328   0      0     c04976e2 00000000 Z iptv_server

      

       僵死进程产生的原因。下面程序在一个循环中每隔10s创建一个子进程。长时间运行后会发现产生了非常多的僵死进程。假设子进程执行时间很短,过程中完美的释放了所有资源,这样的子线程也会成为僵死进程,如下面的程序。一个子进程调用exit退出,资源虽然被系统回收了,但是其进程的数据结构仍保存在系统进程表中。进程的数据结构仍然存在,是Linux希望提供一种机制能让其他进程有机会收集该进程的信息。僵死进程几乎不占内存空间,没有可执行代码,也不能被调度,仅仅在进程列表中保留PID。子进程一般需要父进程负责收尸,如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,那么它就一直保持僵死状态。父进程结束了,僵死的子进程会过继为1号进程init,init负责清理工作。

     

int main(){  while(1){    int pid = fork();    if(pid==0){      childprocess_doSomething();      exit(0);    }else if(pid>0){      parentprocess_doSomething();      usleep(1000*1000*10)    }  }}
      避免僵死进程的方法:

1、父进程通过wait和waitpid等函数等待子进程结束,父进程会被挂起。

pid = fork();            //生成子进程if (pid > 0)            //父进程{   waitpid(pid, &nStatus, 0);    //等待子进程结束,否则子进程会成为僵死进程,一直存在,即便子进程已结束执行}else if (0 == pid)        //子进程{   dosomething();   exit(0);     //子进程结束后,父进程会收到SIGCHLD消息}


2、如果父进程很忙,需要为SIGCHLD安装信号处理函数。父进程收到子进程结束信号后,由信号处理函数回调wait回收。

 struct sigaction sa;  sa.sa_handler = SIG_IGN;  sa.sa_flags = SA_NOCLDWAIT;  sigemptyset(&sa.sa_mask);  sigaction(SIGCHLD, &sa, NULL);


3、如果父进程用signal(SIGCHLD, SIG_IGN)通知内核,告知该子进程自动回收



原创粉丝点击