我试图了解Android如何启动应用程序.问题是Zygote如何(以及为什么)分叉新的Dalvik VM?我不明白为什么不能在同一个Dalvik VM中运行多个应用程序.
Asw*_*mar 141
问:zygote如何正确地分叉Dalvik VM?
简答: Zygote进程基本上冷启动VM启动系统.完成后,它会侦听套接字以获取传入的命令.其他进程(例如ActivityManagerService)在需要应用程序的新进程时将命令写入此套接字.这个命令由Zygote进程读取并调用fork() - 因此子进程现在获得一个预先运行的VM.这就是zygote如何分配Dalvik VM.
答案很长:(这可能很长)加载内核后,init.rc解析并启动本机服务.有了这个,就运行/system/bin/app_process(源代码:frameworks/base/cmds/app_process/app_main.cpp).这最终调用AndroidRuntime.start()函数(源代码:frameworks/base/core/jni/AndroidRuntime.cpp),传递参数com.android.internal.os.ZygoteInit和start-system-server.
所述AndroidRuntime.start()启动Java VM,然后调用ZygoteInit.main()(源代码:框架/碱/核心/ JAVA/COM /机器人/内部/ OS/ZygoteInit.java),向它传递参数start-system-server.
ZygoteInit.main()首先注册zygote套接字(zygote进程侦听套接字以获取传入的命令,并在接收到新命令时,根据请求生成新进程).接下来发生的事情是,它预装了很多类(在frameworks/base/preloaded-classes中列出,最后我检查过,2307行,在android 4.0.4中)和所有系统范围的资源,如drawables,xmls,然后它调用startSystemServer()哪个forfor for new进程com.android.server.SystemServer(源代码:frameworks/base/services/java/com/android/server/SystemServer.java).分支系统服务器是一种特殊情况,因为在所有其他情况下,zygote进程会监听套接字并分叉新命令,我们很快就会看到.
分叉SystemServer后,将runSelectLoopMode()调用一个函数.这是一个while(true)循环,它基本上ZygoteConnection与zygote套接字建立一个并等待命令.当收到命令时,ZygoteConnection.runOnce()调用(源代码:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java)
ZygoteConnection.runOnce()调用Zygote.forkAndSpecialize()(源代码:libcore/dalvik/src/main/java/dalvik/system/Zygote.java),它只调用一个natvie函数来执行fork.因此,与SystemServer的情况一样,创建了一个子进程,该进程具有预热的Dalvik.
问:为什么不能在同一个Dalvik VM中运行多个应用程序?
据我所知,这是一项设计决定.Android人员刚刚决定为每个进程分配一个新VM,以便通过沙盒进行安全保护.
Pau*_*aul 31
不,Dalvik不会跨越流程.
但是,Binder IPC机制可以非常令人信服地使对象看起来迁移到不同的进程及其Dalvik实例.此外,内存管理非常适合在需要它们的所有进程之间共享只读页面.承载典型应用程序的Dalvik进程与zygote分离,所有常见的android库已经映射,因此不必打开新的唯一副本.
另请查看以下链接:
http://davidehringer.com/software/android/The_Dalvik_Virtual_Machine.pdf
http://commonsware.com/blog/Articles/what-is-dalvik.html
只是为了在上面的答案中再添加一点,当 zygote 在接收命令时进行分叉时,它使用写时复制技术。仅当新进程尝试修改内存时才会复制内存。
此外,zygote 在启动时加载的核心库是只读的,无法修改。因此它们不会被复制,而是与新的分叉进程共享。
所有这些都导致了快速启动和更少的内存占用。
| 归档时间: |
|
| 查看次数: |
42750 次 |
| 最近记录: |