从Linux的角度看,Android只是Linux中的一个应用程序而已。 启动Android便是启动一系列的服务和应用模块。从这个角度去理解Android的启动过程会使问题变得简单点。
先启动一个原始进程,加载必要的资源,建立原型,并开启socket等待命令(进程间通信的一种手段)

当原始进程收到命令时,把原始进程的资源信息复制一份,fork一个子进程以节省启动时间。


Android 内核 - 04 Framework 的启动_第1张图片


系统中先创建的进程是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负责后续工作。

Android 内核 - 04 Framework 的启动_第2张图片


zygote 创建的参数定义在 init.rc中, 如下:

servicezygote/system/bin/app_process-Xzygote/system/bin--zygote--start-system-server classmain socketzygotestream660rootsystem onrestartwrite/sys/android_power/request_statewake onrestartwrite/sys/power/stateon onrestartrestartmedia onrestartrestartnetd


Zygote 启动 Step 2ZygoteInit的工作
描述一下 ZygoteInte 的工作大致有以下几个方面
  • 建立/注册 socket
  • 加载资源
  • start SystemServer
  • 进入线程循环状态

Android 内核 - 04 Framework 的启动_第3张图片


1) 函数registerZygoteSocket建立Socket /** *Registersa serversocketforzygote commandconnections * *@throwsRuntimeExceptionwhenopenfails */ privatestaticvoidregisterZygoteSocket(){} 的核心是调用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(); PerformsZygoteprocessinitialization.Loadsandinitializes commonlyusedclasses. 它的核心是 Class.forName(name); 用来创建类的实例
preloadResources(); Loadincommonlyusedresources,sotheycanbesharedacross processes.

preloadOpenGL(); EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)

3)startSystemServer() 创建system_service进程
函数中使用fork方式创建一个新的进程system_service,它的参数定义在了函数中 Stringargs[]={ "-- 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内核-05SystemServer

4)runSelectLoop() 线程进入循环状态
* Runsthezygoteprocess'sselectloop.Acceptsnewconnectionsas theyhappen, * andreadscommandsfromconnectionsonespawn-request's worthatatime.
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()

*Readsonestartcommandfromthecommandsocket.If successful, *a childisforkedanda{@linkZygoteInit.MethodAndArgsCaller} *exceptionisthrowninthatchildwhileintheparentprocess, *themethodreturnsnormally.Onfailure,thechildisnot *spawnedandmessagesareprintedtothelogandstderr.Returns *abooleanstatusvalueindicatingwhetheranend-of-fileonthecommand *sockethasbeenencountered.
从socket 中读取args args=readArgumentList();
分析 args 得到 Arguments
创建子进程 pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids, parsedArgs.debugFlags,rlimits,parsedArgs.mountExternal,parsedArgs.seInfo, parsedArgs.niceName);


更多相关文章

  1. Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
  2. Android 系统(243)---Android进程系列第一篇---进程基础
  3. Android进程保活-自“裁”或者耍流氓
  4. Android进程学习
  5. android 测试读取LEB数据的函数
  6. Android跨进程通信IPC之15——Binder之native层C++篇--注册服务
  7. android使程序进程不被LMK杀死
  8. 通过ddmlib杀死某个android进程的方法
  9. android生命周期函数大全——亲测

随机推荐

  1. Android手机刷机知识小总结
  2. 举例说明android中Bitmap、ListView以及I
  3. Android GPS架构分析(三)
  4. Android(安卓)SQLite性能分析
  5. android修改SeekBar默认样式
  6. android 客户端与服务器交互 UDP方式。
  7. android adb :more than one device or em
  8. Android studio使用MediaPlayer播放在线
  9. android源码下载时,repo下载不成功的问题
  10. Android 常用语句