Android 内核 - 04 Framework 的启动
2016-03-26 21:59
225 查看
从Linux的角度看,Android只是Linux中的一个应用程序而已。
启动Android便是启动一系列的服务和应用模块。从这个角度去理解Android的启动过程会使问题变得简单点。
先启动一个原始进程,加载必要的资源,建立原型,并开启socket等待命令(进程间通信的一种手段)
当原始进程收到命令时,把原始进程的资源信息复制一份,fork一个子进程以节省启动时间。
系统中先创建的进程是Zygote,其他的进程便可以由它进行复制而来。
SystemServer比较特殊,虽然它也是有Zygote孵化而来,但它会负责系统管理的职责,所以单独罗列出来。
Zygote 启动 Step 1
从 app_process 进入ZygoteInit 中
App_main.cpp 在文件夹 frameworks\base\cmds\app_process 中。
AndroidRuntime.cpp 在文件夹 frameworks\base\core\jni 中。
App_main.cpp main函数中会通过参数判断要创建对象的类型,是zygote还是普通application,然后将目标类的名称传递给AndroidRuntime。
由Runtime负责后续工作。
zygote 创建的参数定义在 init.rc中, 如下:
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
Zygote 启动 Step 2 ZygoteInit的工作
描述一下 ZygoteInte 的工作大致有以下几个方面
建立/注册 socket
加载资源
start SystemServer
进入线程循环状态
1) 函数registerZygoteSocket 建立Socket
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {} 的核心是调用 sServerSocket
= new LocalServerSocket(createFileDescriptor(fileDesc)); 建立socket 连接
LocalServerSocket 的构造函数就是建立一个socket的过程,包括bind 和listen。
连接建立完成后,使用这个连接主要是在第4步。
2)预先加载资源 preload()
preload() 函数中主要调用了3个函数
preloadClasses(); Performs Zygote process initialization. Loads and initializes commonly used classes.
它的核心是Class.forName(name); 用来创建类的实例
preloadResources(); Load in commonly used resources, so they can be shared across processes.
preloadOpenGL(); EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
3)startSystemServer() 创建system_service进程
函数中使用fork方式创建一个新的进程system_service,它的参数定义在了函数中
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server", // 进程名称
"com.android.server.SystemServer", // 进程的工作实体
};
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
SystemServer文件保存在 framework\base\services\java\com\android\server中。
这里只保存关于启动过程的信息,关于SystemServe的相系信息整理在:
Android 内核 - 05 SystemServer
4)runSelectLoop() 线程进入循环状态
* Runs the zygote process's select loop. Accepts new connections as they happen,
* and reads commands from connections one spawn-request's worth at a time.
zygote process正式开始工作了,为新的连接做准备,从新的连接读取命令并处理。
runSelectLoop的工作源码:
源码中特意强调了gc()要在select 阻塞之前做,并且避免每个子任务单独的去做GC。
index = selectReadable(fdArray); 作为和子任务通信的接口,用select方式去读取来自socket connect的数据。
如果index == 0,表明是一个新的连接,加入peers的列表
如果index > 0, 表明有数据过来了,需要peers列表中的对象进行处理。
ZygoteConnection的runOnce()
* Reads one start command from the command socket. If successful,
* a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
* exception is thrown in that child while in the parent process,
* the method returns normally. On failure, the child is not
* spawned and messages are printed to the log and stderr. Returns
* a boolean status value indicating whether an end-of-file on the command
* socket has been encountered.
从socket 中读取args
args = readArgumentList();
分析 args 得到 Arguments
创建子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName);
启动Android便是启动一系列的服务和应用模块。从这个角度去理解Android的启动过程会使问题变得简单点。
先启动一个原始进程,加载必要的资源,建立原型,并开启socket等待命令(进程间通信的一种手段)
当原始进程收到命令时,把原始进程的资源信息复制一份,fork一个子进程以节省启动时间。
系统中先创建的进程是Zygote,其他的进程便可以由它进行复制而来。
SystemServer比较特殊,虽然它也是有Zygote孵化而来,但它会负责系统管理的职责,所以单独罗列出来。
Zygote 启动 Step 1
从 app_process 进入ZygoteInit 中
App_main.cpp 在文件夹 frameworks\base\cmds\app_process 中。
AndroidRuntime.cpp 在文件夹 frameworks\base\core\jni 中。
App_main.cpp main函数中会通过参数判断要创建对象的类型,是zygote还是普通application,然后将目标类的名称传递给AndroidRuntime。
由Runtime负责后续工作。
zygote 创建的参数定义在 init.rc中, 如下:
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
Zygote 启动 Step 2 ZygoteInit的工作
描述一下 ZygoteInte 的工作大致有以下几个方面
建立/注册 socket
加载资源
start SystemServer
进入线程循环状态
1) 函数registerZygoteSocket 建立Socket
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {} 的核心是调用 sServerSocket
= new LocalServerSocket(createFileDescriptor(fileDesc)); 建立socket 连接
LocalServerSocket 的构造函数就是建立一个socket的过程,包括bind 和listen。
/** * Crewates a new server socket listening at specified name. * On the Android platform, the name is created in the Linux * abstract namespace (instead of on the filesystem). * * @param name address for socket * @throws IOException */ public LocalServerSocket(String name) throws IOException { impl = new LocalSocketImpl(); impl.create(LocalSocket.SOCKET_STREAM); localAddress = new LocalSocketAddress(name); impl.bind(localAddress); impl.listen(LISTEN_BACKLOG); }
连接建立完成后,使用这个连接主要是在第4步。
2)预先加载资源 preload()
preload() 函数中主要调用了3个函数
preloadClasses(); Performs Zygote process initialization. Loads and initializes commonly used classes.
它的核心是Class.forName(name); 用来创建类的实例
preloadResources(); Load in commonly used resources, so they can be shared across processes.
preloadOpenGL(); EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
3)startSystemServer() 创建system_service进程
函数中使用fork方式创建一个新的进程system_service,它的参数定义在了函数中
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server", // 进程名称
"com.android.server.SystemServer", // 进程的工作实体
};
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
SystemServer文件保存在 framework\base\services\java\com\android\server中。
这里只保存关于启动过程的信息,关于SystemServe的相系信息整理在:
Android 内核 - 05 SystemServer
4)runSelectLoop() 线程进入循环状态
* Runs the zygote process's select loop. Accepts new connections as they happen,
* and reads commands from connections one spawn-request's worth at a time.
zygote process正式开始工作了,为新的连接做准备,从新的连接读取命令并处理。
runSelectLoop的工作源码:
while (true) { int index; /* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done; done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
源码中特意强调了gc()要在select 阻塞之前做,并且避免每个子任务单独的去做GC。
index = selectReadable(fdArray); 作为和子任务通信的接口,用select方式去读取来自socket connect的数据。
如果index == 0,表明是一个新的连接,加入peers的列表
如果index > 0, 表明有数据过来了,需要peers列表中的对象进行处理。
ZygoteConnection的runOnce()
* Reads one start command from the command socket. If successful,
* a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
* exception is thrown in that child while in the parent process,
* the method returns normally. On failure, the child is not
* spawned and messages are printed to the log and stderr. Returns
* a boolean status value indicating whether an end-of-file on the command
* socket has been encountered.
从socket 中读取args
args = readArgumentList();
分析 args 得到 Arguments
创建子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName);
相关文章推荐
- Android基础学习之怎么在Activity启动时获得View的宽高
- Android开源框架Universal-Image-Loader详解
- 浅谈Android MVP设计模式(简单结合RxJava+Retrofit)
- Android资源
- Android 开源框架Universal-Image-Loader---源代码解读
- Android项目通过NDK整合libjpg与libpng
- android 事件机制
- Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解
- Android——AS的Refactor下拉菜单Rename的作用
- 用的最多的Android Studio 快捷键
- JNI学习二之(C源码中Log输出及常见错误)
- Android之aidl文件在AndroidStudio中的使用
- AndroidStudio快捷键汇总
- Android中Handler消息机制浅谈
- Android-布局之FrameLayout
- android之Androidstudio下查找sha1
- 安卓 jni 开发错误 UnsatisfiedLinkError: Native method not found
- Android Studio 下安卓 jni 开发错误 undefined reference to AndroidBitmap_getInfo
- Android应用界面开发_学习笔记_第四周
- Android开源库