再谈“如何学习和理解Android源码”
一. 引子
对于Android源码,网上很多文章都只是列了整个源码的目录结构,这样,习惯性地就将读者引导到按照文章目录结构去阅读的道路上了。而在这篇文章中,贯穿的主线是“进程”,这其实也不难理解,因为计算机中唯一的活着的东西就是“进程”,所以才有kill命令。另外,要阅读的时候,要注重理解系统,而不仅仅是代码,当笔者阅读代码的时候,常常有这种感觉,陷入“惊叹于代码如何如何优美”,而忽略了去更加深入理解系统。另外,之所以称这篇文章为再谈,是因为之前(想想看,已经是3年前的事情了)的一篇博文“Android 启动过程”中已经按照“进程”这个思路大概分析了一下Android 启动过程了。想看的朋友,最好下载资源Android初始化流程:
http://download.youkuaiyun.com/detail/liranke/2037956
而本篇的目的,并不是真正地去分析Android源码,而是试图使读者从另外一个角度去学习和理解Android源码,这也正切合了标题的“如何”二字。
二. 一个进程列表的分析
好了,正式开始我们的“进程”之旅。
关于进程的概念,相信不用在这里繁述了,下面,是用ps命令列出的Android的一个进程列表,这个列表是从真机中而非虚拟机中获得的:
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 548 196 c00b8c14 0000d5cc S /init
root 2 0 0 0 c006bf70 00000000 S kthreadd
root 3 2 0 0 c005cc50 00000000 S ksoftirqd/0
root 4 2 0 0 c007e408 00000000 S watchdog/0
root 5 2 0 0 c0068eec 00000000 S events/0
root 6 2 0 0 c0068eec 00000000 S khelper
root 10 2 0 0 c0224f90 00000000 S suspend/0
root 81 2 0 0 c0068eec 00000000 S kblockd/0
root 89 2 0 0 c01f2f7c 00000000 S kseriod
root 111 2 0 0 c0068eec 00000000 S kmmcd
root 117 2 0 0 c0068eec 00000000 S btaddconn
root 118 2 0 0 c0068eec 00000000 S btdelconn
root 135 2 0 0 c00448e0 00000000 S bpmd
root 141 2 0 0 c008b5f4 00000000 S pdflush
root 142 2 0 0 c008b5f4 00000000 S pdflush
root 143 2 0 0 c008f948 00000000 S kswapd0
root 189 2 0 0 c0068eec 00000000 S aio/0
root 195 2 0 0 c01721f0 00000000 S mtdblockd
root 340 2 0 0 c01b4eb0 00000000 S accessory notif
root 349 2 0 0 c0068eec 00000000 S camera_task/0
root 376 2 0 0 c0061438 00000000 S w1_control
root 378 2 0 0 c0061438 00000000 S w1_bus_master1
root 386 2 0 0 c0068eec 00000000 S charge
root 428 2 0 0 c02ca26c 00000000 S krfcommd
root 430 2 0 0 c0068eec 00000000 S rpciod/0
root 724 2 0 0 c0216908 00000000 S mmcqd
root 726 1 772 180 c019dbc4 afe0c1dc S /system/bin/sh
system 727 1 840 188 c022d8a0 afe0c47c S /system/bin/servicemanager
root 729 1 1920 336 ffffffff afe0c1dc S /system/bin/mountd
root 730 1 704 176 c0257854 afe0ce0c S /system/bin/debuggerd
root 731 1 4132 628 c027e2f8 afe0ce0c S /opl/bin/tcmd
root 732 1 852 248 c00b92b0 afe0c5a4 S /opl/bin/adapter
radio 733 1 12796 648 ffffffff beaab18c S /system/bin/rild
root 734 1 72000 14172 c00b92b0 afe0c5a4 S zygote
root 735 1 33848 4512 ffffffff afe0c47c S /system/bin/mediaserver
root 736 1 1080 216 c00b8c14 bedc021c S /system/bin/dbus-daemon
root 737 1 832 208 c02b6e80 afe0c1dc S /system/bin/installd
root 740 1 856 260 c00b92b0 afe0c5a4 S /opl/bin/bpd
root 741 1 828 172 c00b8c14 afe0d27c S /opl/bin/battmond
root 768 1 720 272 c02265ec afe0c1dc S /system/bin/logcat
root 769 1 716 264 c02265ec afe0c1dc S /system/bin/logcat
root 816 2 0 0 c0068eec 00000000 S battery.0
system 825 734 574128 28360 ffffffff afe0c47c S system_server
radio 877 734 158260 20040 ffffffff afe0d404 S com.android.phone
app_5 879 734 100888 13616 ffffffff afe0d404 S android.process.acore
system 882 734 144664 24296 ffffffff afe0d404 S android.process.omsservice
app_45 884 734 92304 10932 ffffffff afe0d404 S com.motorola.motohome
app_22 890 734 117068 30228 ffffffff afe0d404 S oms.home
app_3 918 734 98760 12652 ffffffff afe0d404 S oms.widgetmanager
app_5 928 734 100888 13336 ffffffff afe0d404 S com.android.inputmethod.borqs
app_24 930 734 105176 19168 ffffffff afe0d404 S com.db4o.servo.search
app_18 960 734 104180 15208 ffffffff afe0d404 S com.android.mms
app_8 979 734 118860 14044 ffffffff afe0d404 S android.process.media
app_9 991 734 91980 12264 ffffffff afe0d404 S com.android.alarmclock
app_15 998 734 103144 12908 ffffffff afe0d404 S oms.dcd
system 1018 734 94732 13792 ffffffff afe0d404 S oms.dm
app_14 1025 734 95636 13036 ffffffff afe0d404 S com.android.calendar
app_42 1041 734 93292 11316 ffffffff afe0d404 S com.motorola.smsautoreg
app_40 1090 734 97152 15192 ffffffff afe0d404 S com.motorola.mtc
app_38 1102 734 93832 12868 ffffffff afe0d404 S com.streamezzo.browser.android
app_26 1115 734 96596 15084 ffffffff afe0d404 S oms.mediacenter
app_37 1126 734 98208 15212 ffffffff afe0d404 S com.hyfsoft.docviewer
app_20 1146 734 99260 15320 ffffffff afe0d404 S com.android.music
app_47 1157 734 100204 15964 ffffffff afe0d404 S com.motorola.camera
app_11 1183 734 122672 23576 ffffffff afe0d404 S com.android.browser
app_6 1199 734 117032 20388 ffffffff afe0d404 S oms.mobilemusic
system 1244 734 99292 15940 ffffffff afe0d404 S com.android.settings
app_23 1311 734 96932 16004 ffffffff afe0d404 S oms.bru
root 1334 2 0 0 c0216908 00000000 S mmcqd
app_8 1351 734 100308 15876 ffffffff afe0d404 S com.android.camera
app_1 1424 734 111904 17024 ffffffff afe0d404 S oms.messaging
app_4 1436 734 101172 15504 ffffffff afe0d404 S oms.mail
app_2 1484 734 100716 18128 ffffffff afe0d404 S com.ms
app_16 1663 734 101024 16748 ffffffff afe0d404 S oms.android.filemanager
root 1684 1 3364 176 ffffffff 0000e8f4 S /sbin/adbd
root 1692 1684 776 348 c0059cd4 afe0d0ac S /system/bin/sh
root 1724 1692 920 356 00000000 afe0c1dc R ps
OK,让我们看看这个长长的列表包含了些什么信息吧:
1. 大家知道,linux系统中,init的pid是就是1,而且它是linux内核启动之后的第一个进程,而它的
ppid(父进程)是0,这也表明,0也是个一个进程。事实上,linux内核的pid就是0。
2. pid 为2的进程是kthreadd,而它的父进程也是内核(pid为0的进程),这个进程和它的子进程(诸如
ksoftirqd之类的ppid为2的进程)一起,可以处理包含但不限于内核cpu调度或者事件处理的一些功能。
3. 接下来,我们看到的了一系列以ppid为1的进程,包括我们熟悉的sh,servicemanager,
mountd,rild,zygote,mediaserver,logcat等等。它们的父进程是init,仔细阅读init的代码,就会发
现,其实,这些是在init.rc中指定的。另外,以上这些进程,都是一些C/C++代码写的,事实上,这时
候,java虚拟机(jvm)还没有启动,所以,现在根本不能运行java代码,也谈不上Android framework,
而至于Activity之类的,系统根本不知道是什么东东。后面,会着重介绍servicemanager,zygote。
而其它的,读者可以自己分析。
4. 从system_server开始,包括系统自己带的android应用程序,以及用户实现的android应用程序,它
们的父进程都是zygote。我们知道,每一个android应用程序都是一个jvm,所以,读者可以猜想,
zygote中会进行java虚拟机的装载以及runtime的初始化。另外,整个进程列表中,并没有看到Android
Framework相关的进程列表。事实上,读者的想法一点没有错,zygote初始化了jvm,而system_server就
是Android Framework组件的进程所在。因此,毫不夸张地说,zygote和system_server是Android
Framework的基石。
5. 那么,上面这个进程列表是如何产生的。看最后三行,不难理解,我们从adbd 启动了一个shell,然
后,输入ps命令,就得到了上面这个进程列表。
6. 另外,从第一列USER(用户)的用度看,所有的Android应用程序(包括系统自带的)都是app_XXX,
熟悉Android应用程序开发的读者也知道,每一个Android应用程序都是独立的,有自己的UID。
7. 事实上,如果将上面所有的进程(特别是用户为root, sysytem)都理解了的话,那么,也就相当于
理解了Android系统。
8. 从以上列表,你还想到了什么?
三. 进程/system/bin/servicemanager:
1. servicemanager是一个可执行程序,代码位于:frameworks/base/cmds/servicemanager;
2. servicemanager是init通过init.rc加载的第一个进程;
3. 查看servicemanager的原码(service_manager.c),最重要的一句:binder_open(128*1024); 哦,我们看到了binder,而且它申请的内存空间是128*1024。正是有了servicemanager,系统的service和用户自己开发的service才可以正常运行;
4. 可以想到的是,binder是在servicemanager中进行数据结构的初始化,并打开了"/dev/binder"。
四. 进程zygote:
1. 代码位置:frameworks\base\core\java\com\android\internal\os
2. 主要作用:
creat Jvm->fork SystemServer->start system_server
3. 详细请参考: Android初始化流程:
http://download.youkuaiyun.com/detail/liranke/2037956
五. 进程system_server
1. 代码位置:frameworks\base\services\java\com\android\server:
2. 主要作用:初始化核心组件,事实上,就是Android framework层的组件,例如,POWER_SERVICE,ActivityManagerService,PackageManagerService,batteryService,LightsService,VibratorService,AlarmManagerService,WindowManagerService......,这些组件,大部分都是以service的形式存在的。正是因为如此,我们才可以在这些组件的基础上进行应用程序的开发。所以,frameworks\base\core\java\com\android\internal\os\SystemServer.java这个文件是必须要仔细看的,事实上,这个文件本身的代码结构是非常简单的。
3. 至此,已经到了Android framework层了,剩下的就是那些组件各自的功能了,例如ActivityManagerService,PackageManagerService,WindowManagerService......
六. 后记
通过以上分析,我们就基本了解了Android的系统架构为什么是现在这个样子了。另外,在这个基础之上,如果感兴趣的话,再去分析和理解binder机制,adbd等,就会对系统更加熟悉了。祝读者在Android领域中展现出自己独特的风采!
本文聚焦Android系统架构,以进程视角解读系统启动、关键进程如servicemanager、zygote和system_server的作用及相互关系,帮助开发者从不同角度理解Android源码。
1474

被折叠的 条评论
为什么被折叠?



