浅谈Cfork子进程
来源:互联网 发布:大数据资源管理平台 编辑:程序博客网 时间:2024/05/22 17:08
首先,来谈一谈这个技术适用的场合吧。当一个用户把我们开发的APP卸载的时候,我们可能需要进行问卷调查,或者是进行一些推广。还有一种情况,就是像QQ,微信这样的实时通讯软件,需要实时占用着进程,可是Android有个特性,就是当内存不够的时候,会杀死一些进程,可能,这个被杀死的进程就是我们需要一直生存的进程。那么,这个时候C语言的fork函数就登场了,我们可以用JNI调用fork函数,然后通过返回值,进行我们想要的操作。具体我们来看看代码实现。
首先我们创一个工程就命名为Cfork。
MainActivity
public class MainActivity extends Activity { static{ System.loadLibrary("cfork"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void fork(View v){ cfork(); } public native void cfork();}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="fork" android:text="分叉子进程" /></RelativeLayout>
为了可以调试,我们加上这样一个头文件eben_hpc_log.h
#ifndef _Included_hpc_Log#define _Included_hpc_Log#ifdef __cplusplusextern "C" {#endif#include <android/log.h>// 宏定义类似java 层的定义,不同级别的Log LOGI, LOGD, LOGW, LOGE, LOGF。 对就Java中的 Log.i log.d#define LOG_TAG "hpc -- JNILOG" // 这个是自定义的LOG的标识//#undef LOG // 取消默认的LOG#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__)#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__)#ifdef __cplusplus}#endif#endif
cfork.c
#include <jni.h>#include <unistd.h>#include <stdio.h>#include "eben_hpc_log.h"int ppid;JNIEXPORT void JNICALL Java_com_mengxin_cfork_MainActivity_cfork (JNIEnv * env, jobject obj){ int pid = fork(); //fork成功的分叉出一个子进程 会返回当前进程的id 但是只能在主进程中fork成功 //在子进程中运行fork 会返回0 但是不能再分叉出新的进程 //fork的返回值可能三种 >0 == 0 <0 FILE* file; if(pid>0){ LOGD("pid = %d",pid); }else if(pid == 0){ //拿到父进程的进程编号 LOGD("pid == 0"); while(1){ ppid = getppid(); //如果父进程的进程编号为1 说明父进程被杀死了 if(ppid == 1){ LOGD("ppid =%d",ppid); file = fopen("/data/data/com.mengxin.cfork","r"); if(file == NULL){ //打开网页 调用am命令 //如果API16以上加上"--user","0",以下不用加 execlp("am", "am", "start", "--user","0", "-a", "android.intent.action.VIEW", "-d", "http://www.baidu.com", (char *) NULL); }else{ execlp("am", "am", "start", "--user","0", "-n", "com.mengxin.cfork/com.mengxin.cfork.MainActivity",(char *) NULL); } break; } LOGD("sub process is running"); sleep(2); } }else{ LOGD("pid<0 "); }}
这里补充一点 am 命令
- am命令 :在adb shell里可以通过am命令进行一些操作 如启动activity Service 启动浏览器等等
- am命令的源码在Am.java中, 在adb shell里执行am命令实际上就是启动一个线程执Am.java的main方法,am命令后面带的参数都会当作运行时的参数传递到main函数中
- am命令可以用start子命令,并且带指定的参数
- 常见参数: -a: action -d data -t 表示传入的类型 -n 指定的组件名字
- 举例: 在adb shell中通过am命令打开网页
- am start –user 0 -a android.intent.action.VIEW -d http://www.baidu.com
- 通过am命令打开activity
- am start –user 0 -n com.itheima.fork/com.itheima.fork.MainActivity
(系统sdk版本>16 需要加上–user 0 , <16不需要加)
execlp c语言中执行系统命令的函数
- execlp() 会从PATH环境变量所指的目录中查找符合参数file的文件找到后就执行该文件, 第二个参数开始就是执行这个文件的 args[0],args[1] 最后一个参数用(char*)NULL结束
- android开发中 execlp函数对应android的path路径为system/bin/目录
调用格式
execlp("am", "am", "start", "--user","0","-a", "android.intent.action.VIEW", "-d", "http://www.baidu.com", (char *) NULL);
最后修改build.gradle
apply plugin: 'com.android.application'android { compileSdkVersion 24 buildToolsVersion "24.0.2" defaultConfig { applicationId "com.mengxin.cfork" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" ndk { ldLibs "log" moduleName "cfork" //生成的so名字 //abiFilters "armeabi" //输出指定三种abi体系结构下的so库。目前可有可无。 abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。 } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.0'}
0 0
- 浅谈Cfork子进程
- shell浅谈之九子shell与进程处理
- shell浅谈之九子shell与进程处理
- 浅谈进程
- 子进程
- 子进程
- 子进程
- 进程与子进程
- 父进程 子进程
- 父进程子进程
- 浅谈 最大子矩阵
- Windows进程/线程浅谈
- Windows进程/线程浅谈
- Windows进程/线程浅谈
- 《浅谈android进程》
- Windows进程/线程浅谈
- 浅谈线程和进程
- 浅谈linux进程调度
- 初识dalvik虚拟机,和Android开发环境搭建
- 看牛B架构师是如何架设自己的Linux开发环境
- 异步编程模型
- 剖析金额不能用浮点数表示的原因
- RGB转YUV420
- 浅谈Cfork子进程
- crontab的基本用法介绍
- 简要分析任务与线程池
- 黑盒测试——边界值划分法
- cookie实现简单的用户用户验证与记住密码
- Struts2+jQuery,使用ajax传递JSON数据
- RTEMS硬实时操作系统简介
- js预编译和解析
- 一个fork的面试题