通过JNI的方式 android 防止进程被杀

Posted Mark_YPQ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过JNI的方式 android 防止进程被杀相关的知识,希望对你有一定的参考价值。

通过JNI的方式(NDK编程),fork()出一个子线程作为守护进程,轮询监听服务状态。守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。而守护进程的会话组和当前目录,文件描述符都是独立的。后台运行只是终端进行了一次fork,让程序在后台执行,这些都没有改变。

那么我们先来看看android4.4的源码,ActivityManagerService(源码/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java)是如何关闭在应用退出后清理内存的:

[java]  view plain  copy  
  1. Process.killProcessQuiet(pid);  
应用退出后,ActivityManagerService就把主进程给杀死了,但是,在 Android5.0 中,ActivityManagerService却是这样处理的:

[java]  view plain  copy  
  1. Process.killProcessQuiet(app.pid);  
  2. Process.killProcessGroup(app.info.uid, app.pid);  
就差了一句话,却差别很大。 Android5.0在应用退出后,ActivityManagerService不仅把主进程给杀死,另外把主进程所属的进程组一并杀死,这样一来,由于子进程和主进程在同一进程组,子进程在做的事情,也就停止了 ...要不怎么说Android5.0在安全方面做了很多更新呢...

那么,有没有办法让子进程脱离出来,不要受到主进程的影响,当然也是可以的。那么,在C/C++层是如何实现的呢?先上关键代码:

[cpp]  view plain  copy  
  1. /** 
  2.  * srvname  进程名 
  3.  * sd 之前创建子进程的pid写入的文件路径 
  4.  */  
  5. int start(int argc, char* srvname, char* sd)   
  6.     pthread_t id;  
  7.     int ret;  
  8.     struct rlimit r;  
  9.   
  10.     int pid = fork();  
  11.     LOGI("fork pid: %d", pid);  
  12.     if (pid < 0)   
  13.         LOGI("first fork() error pid %d,so exit", pid);  
  14.         exit(0);  
  15.      else if (pid != 0)   
  16.         LOGI("first fork(): I'am father pid=%d", getpid());  
  17.         //exit(0);  
  18.      else  //  第一个子进程  
  19.         LOGI("first fork(): I'am child pid=%d", getpid());  
  20.         setsid();  
  21.         LOGI("first fork(): setsid=%d", setsid());  
  22.         umask(0); //为文件赋予更多的权限,因为继承来的文件可能某些权限被屏蔽  
  23.   
  24.         int pid = fork();  
  25.         if (pid == 0)  // 第二个子进程  
  26.             FILE  *fp;  
  27.             sprintf(sd,"%s/pid",sd);  
  28.             if((fp=fopen(sd,"a"))==NULL) //打开文件 没有就创建  
  29.                 LOGI("%s文件还未创建!",sd);  
  30.                 ftruncate(fp, 0);  
  31.                 lseek(fp, 0, SEEK_SET);  
  32.               
  33.             fclose(fp);  
  34.             fp=fopen(sd,"rw");  
  35.             if(fp>0)  
  36.                 char buff1[6];  
  37.                 int p = 0;  
  38.                 memset(buff1,0,sizeof(buff1));  
  39.                 fseek(fp,0,SEEK_SET);  
  40.                 fgets(buff1,6,fp);  //读取一行(pid)  
  41.                 LOGI("读取的进程号:%s",buff1);  
  42.                 if(strlen(buff1)>1) // 有值  
  43.                     kill(atoi(buff1), SIGTERM); // 把上一次的进程干掉,防止重复执行  
  44.                     LOGI("杀死进程,pid=%d",atoi(buff1));  
  45.                   
  46.               
  47.             fclose(fp);  
  48.             fp=fopen(sd,"w");  
  49.             char buff[100];  
  50.             int k = 3;  
  51.             if(fp>0)  
  52.                 sprintf(buff,"%lu",getpid());  
  53.                 fprintf(fp,"%s\\n",buff); // 把进程号写入文件  
  54.               
  55.             fclose(fp);  
  56.             fflush(fp);  
  57.   
  58.             LOGI("I'am child-child pid=%d", getpid());  
  59.             chdir("/"); //<span style="font-family: Arial, Helvetica, sans-serif;">修改进程工作目录为根目录,chdir(“/”)</span>  
  60.             //关闭不需要的从父进程继承过来的文件描述符。  
  61.             if (r.rlim_max == RLIM_INFINITY)   
  62.                 r.rlim_max = 1024;  
  63.               
  64.             int i;  
  65.             for (i = 0; i < r.rlim_max; i++)   
  66.                 close(i);  
  67.               
  68.   
  69.             umask(0);  
  70.             ret = pthread_create(&id, NULL, (void *) thread, srvname); // 开启线程,轮询去监听启动服务  
  71.             if (ret != 0)   
  72.                 printf("Create pthread error!\\n");  
  73.                 exit(1);  
  74.               
  75.             int stdfd = open ("/dev/null", O_RDWR);  
  76.             dup2(stdfd, STDOUT_FILENO);  
  77.             dup2(stdfd, STDERR_FILENO);  
  78.          else   
  79.             exit(0);  
  80.           
  81.       
  82.     return 0;  
  83.   
  84.   
  85. /** 
  86.  * 启动Service 
  87.  */  
  88. void Java_com_yyh_fork_NativeRuntime_startService(JNIEnv* env, jobject thiz,  
  89.         jstring cchrptr_ProcessName, jstring sdpath)   
  90.     char * rtn = jstringTostring(env, cchrptr_ProcessName); // 得到进程名称  
  91.     char * sd = jstringTostring(env, sdpath);  
  92.     LOGI("Java_com_yyh_fork_NativeRuntime_startService run....ProcessName:%s", rtn);  
  93.     a = rtn;  
  94.     start(1, rtn, sd);  
  95. Android防止进程被杀

    Android防止进程被杀

    Android 通过JNI实现守护进程

    Android 通过JNI实现守护进程

    Android 通过JNI实现守护进程,使得Service服务不被杀死

    Android - 禁用权限后,进程被杀?