一、app_process与Zygote
Android中,创建进程的方式有4种,其中app_process和Zygote有什么不同呢?
Android系统内核初始化完毕后,进入用户空间启动的第一个进程叫init 他是Android系统所有进程的祖先,这个进程启动后会初始化文件系统。Zygote主要负责如下任务
- 负责启动java虚拟机
- 加载很多需要预加载的类和系统资源
- 负责启动systemServer ,systemServer 会启动android中的所有服务,基本上完成了上层框架的所有功能。
- 负责初始化新进程,其实就是fork app的独立进程,比如启动一个application,那么zygote就负责为新启动的activityThread建立进程,并调用AppRuntime 、activityThread中的main,或进行初始化。
对于init来说zygote其实就是一个很普通的服务
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
我们从其中的调用逻辑发现,实际上zygote进程是通过app_process工具创建的,可见app_process在Android系统中的作用也很重要。
二、app_process
int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char *arg;
argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
// Next arg is parent directory
if (i < argc) {
runtime.mParentDir = argv[i++];
}
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
app_process参数格式如下:
app_process [vm-options] [工作目录] [options] 类名 [类的main方法参数] [类的main方法参数] ....
参数解释如下
vm-options – VM 选项
work-dir –工作目录(如/system/bin,/data/app,/data/...)
options –运行的参数 :
–-zygote
–-start-system-server
–-application (api>=14)
–-nice-name=nice_proc_name (api>=14) (只有非--zygoate模式下该选项才会生效)
[启动类名] –包含main方法的主类 (如com.android.internal.os.WrapperInit)
main-options –启动时候传递到main方法中的参数
一个完整的例子
app_process -Djava.class.path=/sdcard/classes.dex /data/local/tmp --application --nice-name=helloservice com.apptest.bash.HelloWorld 1 2 a
一般来说,默认都是--application模式,加上这个参数和不加,都能创建进程,只是IO输入输出的位置不同
此外,我们还可以使用apk
app_process -Djava.class.path=/sdcard/app.apk /data/local com.apptest.bash.HelloWorld
关于几种模式的
- 传入 –zygote 会启动 com.android.internal.os.ZygoteInit ,否则启动 com.android.internal.os.RuntimeInit 。
- –start-system-server 只在启动 zygote 时有效。
- 在非 zygote 模式中,有无 –application 的选项的区别只是是否将 stdout 和 stderr 重定向到 AndroidPrintStream。
- 只有在非 zygote 的情况下,–nice-name= 选项有效。
从几种模式我们知道,app_process都会走虚拟机相关初始化逻辑,因此,可以确定的是app_process启动的并不是普通的java程序
我们可以证明一下
public class HelloWorld {
public static void main(String[]args){
int num = 0;
while (true) {
System.out.println("["+android.os.Process.myPid()+" ]Hello, app_process "+num);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
}
}
}
执行如下命令
app_process -Djava.class.path=/sdcard/app.apk /data/local --nice-name=hellworld com.apptest.bash.HelloWorld
这个类中调用了android.os.Process.myPid(),运行结果如下,可以发现,Android相关api可以正常运行
[8062 ]Hello, app_process 0
[8062 ]Hello, app_process 1
[8062 ]Hello, app_process 2
[8062 ]Hello, app_process 3
[8062 ]Hello, app_process 4
[8062 ]Hello, app_process 5
[8062 ]Hello, app_process 6
[8062 ]Hello, app_process 7
[8062 ]Hello, app_process 8
[8062 ]Hello, app_process 9
可以明确知道,Android相关服务通过 com.android.internal.os.RuntimeInit进行了初始化, 这才是 app_process 真实启动类
三、app_process的父进程
我们知道,Android中app主进程和其他进程都是Zygote的子进程,并且相互隔离,那么app_process启动的进程又是怎么的呢?
对于用户而言,我们一般都是--application模式启动,影响进程父进程的主要因素和用户相关。
总结如下:
- 在shell进程调用app_process,子进程的父进程为shell,用户id为root或者shell
- 在用户app中调用app_process,子进程的父进程为init,用户id和app的用户一致。
在Android系统中,用户id一致,意味着进程之间的相关信息可以互相访问,包括杀进程,清理私有目录都会被允许。