通过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
- Process.killProcessQuiet(pid);
[java] view plain copy
- Process.killProcessQuiet(app.pid);
- Process.killProcessGroup(app.info.uid, app.pid);
那么,有没有办法让子进程脱离出来,不要受到主进程的影响,当然也是可以的。那么,在C/C++层是如何实现的呢?先上关键代码:
[cpp] view plain copy
- /**
- * srvname 进程名
- * sd 之前创建子进程的pid写入的文件路径
- */
- int start(int argc, char* srvname, char* sd)
- pthread_t id;
- int ret;
- struct rlimit r;
- int pid = fork();
- LOGI("fork pid: %d", pid);
- if (pid < 0)
- LOGI("first fork() error pid %d,so exit", pid);
- exit(0);
- else if (pid != 0)
- LOGI("first fork(): I'am father pid=%d", getpid());
- //exit(0);
- else // 第一个子进程
- LOGI("first fork(): I'am child pid=%d", getpid());
- setsid();
- LOGI("first fork(): setsid=%d", setsid());
- umask(0); //为文件赋予更多的权限,因为继承来的文件可能某些权限被屏蔽
- int pid = fork();
- if (pid == 0) // 第二个子进程
- FILE *fp;
- sprintf(sd,"%s/pid",sd);
- if((fp=fopen(sd,"a"))==NULL) //打开文件 没有就创建
- LOGI("%s文件还未创建!",sd);
- ftruncate(fp, 0);
- lseek(fp, 0, SEEK_SET);
- fclose(fp);
- fp=fopen(sd,"rw");
- if(fp>0)
- char buff1[6];
- int p = 0;
- memset(buff1,0,sizeof(buff1));
- fseek(fp,0,SEEK_SET);
- fgets(buff1,6,fp); //读取一行(pid)
- LOGI("读取的进程号:%s",buff1);
- if(strlen(buff1)>1) // 有值
- kill(atoi(buff1), SIGTERM); // 把上一次的进程干掉,防止重复执行
- LOGI("杀死进程,pid=%d",atoi(buff1));
- fclose(fp);
- fp=fopen(sd,"w");
- char buff[100];
- int k = 3;
- if(fp>0)
- sprintf(buff,"%lu",getpid());
- fprintf(fp,"%s\\n",buff); // 把进程号写入文件
- fclose(fp);
- fflush(fp);
- LOGI("I'am child-child pid=%d", getpid());
- chdir("/"); //<span style="font-family: Arial, Helvetica, sans-serif;">修改进程工作目录为根目录,chdir(“/”)</span>
- //关闭不需要的从父进程继承过来的文件描述符。
- if (r.rlim_max == RLIM_INFINITY)
- r.rlim_max = 1024;
- int i;
- for (i = 0; i < r.rlim_max; i++)
- close(i);
- umask(0);
- ret = pthread_create(&id, NULL, (void *) thread, srvname); // 开启线程,轮询去监听启动服务
- if (ret != 0)
- printf("Create pthread error!\\n");
- exit(1);
- int stdfd = open ("/dev/null", O_RDWR);
- dup2(stdfd, STDOUT_FILENO);
- dup2(stdfd, STDERR_FILENO);
- else
- exit(0);
- return 0;
- /**
- * 启动Service
- */
- void Java_com_yyh_fork_NativeRuntime_startService(JNIEnv* env, jobject thiz,
- jstring cchrptr_ProcessName, jstring sdpath)
- char * rtn = jstringTostring(env, cchrptr_ProcessName); // 得到进程名称
- char * sd = jstringTostring(env, sdpath);
- LOGI("Java_com_yyh_fork_NativeRuntime_startService run....ProcessName:%s", rtn);
- a = rtn;
- start(1, rtn, sd);
- Android防止进程被杀