在学习Andorid系统服务之前,为了便于理解,先看下系统进程及主要服务在手机中的信息。如下如果涉及到源码,使用的是android8.0的代码,不排除个别代码是从其他博客中复制的或者不同的android8.0代码有个别差异,故如果有和读者理解及查看不一样的地方,请读者注意
直观的感受下系统进程
开启一个 android 5.0的模拟(小编使用android 7.0的模拟器及android 8.0的华为手机,使用 adb shell ps 命令没有信息,这个问题已经解决,见Android 高版本(8、9、10)查看手机中进程信息、线程信息)
打开一个cmd终端,输入如下命令
adb shell
ps #列出系统中所有进程信息
USER:进程当前用户;
PID(Process Id):当前进程id;
PPID(Process Parent ID):父进程ID;
VSIZE(Virtual Size):当前进程虚拟内存的大小;
RSS(Resident Set Size):实际驻留在内存中的没存大小;
WCHAN:休眠进程在内核中的地址;
PC(program counter):计算机中提供要从[存储器]中取出的下一个指令地址的[寄存器];
NAME:进程状态值及名称;一般情况下,如果是app,则进程名默认是其包名
Android中 adb shell ps 查看手机中进程信息
高版本查看进程问题
adb shell ps -A
Android高版本adb shell ps不能查看其他进程问题
这里看几个关键的进程
servicemanager进程,其是由init进程fork的。其先于zygote进程创建
zygote、system_server进程。zygote输入root用户的进程
可以看到很多进程的PPID都是 1182,即它们的父进程是zygote64,即网上常说的zygote进程,system_server的父进程也是zygote进程,所以它们都是zygote进程孵化(fork)的,而zygote进程是由1号进程 init进程孵化的。
ps |grep keyword
keyword是我们想要找的进程名字的全称或者是一部分,也就是app的包名或者包名的一部分,比如我们的包名是com.xxxxx.yyyy,keyword可以是com.xxxxx.yyyy,也可以是xxxxx或者yyyy。该命令会把我们要找的进程范围缩减到最小
另外,这里顺便补充两种杀死进程的方法:
第一种:kill -9 进程号
举例:adb shell kill -9 1137
第二种:adb shell am force-stop 包名全称,该方法不支持部分匹配,所以一定要是包名的全称。
举例:adb shell am force-stop com.xxxxx.yyyy
在ps命令中,“-t”选项可以开启线程查看
如:代码中创建ActivityManager线程的地方
注意:这里线程名称显示字符长度是有限制的。故显示为ActivityManager名称的线程可能就是ActivityManagerService的线程,同样PowerManagerSer名称的线程就是PowerManagerService线程。很多常用的系统服务都是一个特定的线程,运行在system_server进程中。小编在android 4.4的模拟器上能看到WindowManager字样的线程名,但是5.0的模拟器没有看到,有可能改名称了,这个需要跟源码。
Android的ps命令参数: -t -x -P -p -c [pid|name]
adb shell查看进程方法
ADB之adb shell ps命令查看信息
Android中 adb shell ps 查看手机中进程信息
Android中 adb shell ps 查看手机中进程信息
zygote fork是单线程,为了避免造成死锁或者状态不一致等问题
我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类系统资源等等,这些都是非常耗时的,如果能在zygote里就给这些必要的初始化工作做好,子进程在fork的时候就能直接共享,那么这样的话效率就会非常高。这个就是zygote存在的价值,这一点呢SystemServer是替代不了的,主要是因为SystemServer里跑了一堆系统服务,这些是不能继承到应用进程的。而且我们应用进程在启动的时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一堆乱七八糟的东西。所以呢,不如给SystemServer和应用进程里都要用到的资源抽出来单独放在一个进程里,也就是这的zygote进程,然后zygote进程再分别孵化出SystemServer进程和应用进程。孵化出来之后,SystemServer进程和应用进程就可以各干各的事了。
android间的进程通信是使用Binder,唯独Zygote和SystemService是使用socket
第一种解释:
第一个原因,我们可以设想一下采用binder调用的话该怎么做,首先zygote要启用binder机制,需要打开binder驱动,获得一个描述符,再通过mmap进行内存映射,还要注册binder线程,这还不够,还要创建一个binder对象注册到serviceManager,另外AMS要向zygote发起创建应用进程请求的话,要先从serviceManager查询zygote的binder对象,然后再发起binder调用,这来来回回好几趟非常繁琐,相比之下,zygote和SystemServer进程本来就是父子关系,对于简单的消息通信,用管道或者socket非常方便省事。第二个原因,如果zygote启用binder机制,再fork出SystemServer,那么SystemServer就会继承了zygote的描述符以及映射的内存,这两个进程在binder驱动层就会共用一套数据结构,这显然是不行的,所以还得先给原来的旧的描述符关掉,再重新启用一遍binder机制,这个就是自找麻烦了。
android大致的启动三段式
进程启动 -> 准备工作 -> loop循环(接收消息,处理消息 socket,messagequeue消息,binder驱动发来的消息)
android 学习之 zygote作用
第二种解释:
怕父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁,所以fork不允许存在多线程。而非常巧的是Binder通讯偏偏就是多线程,所以干脆父进程(Zgote)这个时候就不使用binder线程。
Android Framework层学习——为什么SystemServer进程与Zygote进程通讯采用Socket而不是Binder
在看网上技术博客的时候,你会发现有说到app_process进程的
Zygote是一个Native的应用程序,是由init进程根据init.rc文件中的配置项创建的,它最初的名字为“app_process”,这个名字是在Android.mk(路径为frameworks\base\cmds\app_process)文件中指定的,
LOCAL_MODULE:= app_process
include $(BUILD_EXECUTABLE)
在运行的过程中,app_process通过将自己的名字换成了“zygote”,就成了现在我们看到的zygote。
frameworks\base\cmds\app_process\app_main.cpp中
int main(int argc, char* const argv[])
{
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[i]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.
//
// As an exception to the above rule, anything in "spaced commands"
// goes to the vm even though it has a space in it.
const char* spaced_commands[] = { "-cp", "-classpath" };
// Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
bool known_command = false;
int i;
for (i = 0; i < argc; i++) {
if (known_command == true) {
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add known option '%s'", argv[i]);
known_command = false;
continue;
}
for (int j = 0;
j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
if (strcmp(argv[i], spaced_commands[j]) == 0) {
known_command = true;
ALOGV("app_process main found known command '%s'", argv[i]);
}
}
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add option '%s'", argv[i]);
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;//设置进程名称为 zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
if (!LOG_NDEBUG) {
String8 restOfArgs;
char* const* argv_new = argv + i;
int argc_new = argc - i;
for (int k = 0; k < argc_new; ++k) {
restOfArgs.append("\"");
restOfArgs.append(argv_new[k]);
restOfArgs.append("\" ");
}
ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
}
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
Init.rc文件中zygote的配置:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
app_process对应的源文件为App_main.cpp,它的main函数处理完传入的参数后,便将进程的名字改成了“zygote”,然后最重要的工作就交给了AppRuntime类的start方法:
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server": "");
AppRuntime类继承了AndroidRuntime类,并重载了onStarted、onZygoteInit和onExit函数。
Android启动流程------Zygote和Systemserver的分析
SystemServer:这个类 每执行到一个阶段都会调用SystemServiceManager的startBootPhase函数
我们下面看下SystemServiceManager的startBootPhase函数,它会把mServices中的service取出来,调用onBootPhase函数
SystemServiceManager:这个类只是管理各个service,用SystemServiceManager启动service的时候,会把service加入自己的链表。并且调用相应service的onStart函数。
SystemService:这个类一般是一些系统service来继承这个类。例PowerManagerService,其中实现了onStart和onBootPhase函数,其中publishBinderService函数是SystemService中的函数,最后是调用了ServiceManager.addService。
ServiceManager:这个类,是java层用来和servicemanager进程通信的
Zygote与system_server共存亡
system_server是一个很重要的进程,如果挂了,Zygote必须重启,如果不重启,手机就会进入假死的状态,手机黑屏,无声,无法跟用户交互等
system_server采用抛出异常和捕捉异常的方式启动,可以清除进程的堆栈,减少内存占用。
system_server与Zygote共存亡是通过父进程调用waitpid的方式监听子进程system_server的死亡,当子进程死亡的时候,父进程就自杀
Framework基础:源于异常的System_Server与受精卵Zygote的共存亡
Android系统的分层
android可以理解为一直循环处理消息的系统。
android\system\core\init\init.cpp
init.cpp中的main方法是其入口函数,主要做:
创建文件,挂载,初始化安全策略,初始化属性相关资源,解析init.rc文件,性能分析和执行其它进程
Android系统启动(二)-Init篇
Android系统启动分析(Init->Zygote->SystemServer->Home activity)
可以理解为其是不断循环处理socket消息的进程。
1、开启虚拟机
2、注册JNI
3、创建Socket服务端
4、预加载资源、类、虚拟机实例
5、启动system_server进程
6、循环等待socket消息
当与system_server交互时,system_server是socket客户端,zygote是socket服务端。
zygote进程是由init进程启动的,init进程(linux中的1号进程)启动之后会在system/core/init/init.cpp中解析init.rc文件,init.rc文件路径
android/system/core/rootdir/init.rc
其中import导入部分
import /init.${ro.zygote}.rc
init.rc不再直接引入一个固定的文件,而是根据属性ro.zygote(ro.zygote的值是在mk文件中定义的,知道即可)的内容来引入不同的文件。因为Android 5.0以后开始支持64位程序,为了兼容32位和64位才这样定义。不同的zygote.rc内容大致相同,主要区别体现在启动的是32位,还是64位的程.init.zygote32_64.rc和init.zygote64_32.rc会启动两个进程,且存在主次之分。
在system/core/rootdir/这个路径下还包括四个关于zygote的rc文件。分别是Init.zygote32.rc,Init.zygote32_64.rc,Init.zygote64.rc,Init.zygote64_32.rc。通过ro.zygote的定义来决定使用哪个文件。
android/system/core/rootdir/Init.zygote32.rc文件中,代码如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main #class是一个option,指定zygote服务的类型是main
priority -20
user root
group root readproc
socket zygote stream 660 root system #socket关键字表示一个option。创建一个名为dev/socket/zygote,类型为stream,权限660的socket。
onrestart write /sys/android_power/request_state wake #onrestart是一个option,说明在zygote重启时需要执行的command
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 //创建子进程时,向/dev/cpuset/foreground/tasks 写入pid
xx.rc文件中的语法规则。其中有许多service启动,这些service通常不是普通的服务,文档里面的称呼是daemon(守护进程).
所谓守护进程就是这些服务进程会在系统初始化时启动,并一直运行于后台,直到系统关闭时终止。
32位的 zygote进程对应的二进制文件是 /system/bin/app_process
开启一个x86即32位虚拟机,可以看到
zygote最初的名字是app_process,他对应的源代码是
android_8.0\frameworks\base\cmds\app_process\app_main.cpp
zygote原理分析
Android Zygote介绍
Android 8.0 系统启动流程之zygote进程(八)
负责启动和管理framework,包含AMS,PMS,WMS等服务。
不断循环处理binder消息。当和app交互的时候,app是客户端,SystemServer是服务端。它一直在监听创建新进程请求,如果有请求,则向Zygote发送请求。和Zygote交互的时候SystemServer是socket客户端,Zygote是socket服务端。SystemServer进程调用Process.start向Zygote进程发送 fork进程的参数,由Zygote进程fork进程
不断循环处理Message消息
Zygote是什么
Android系统启动(一)开篇