Android 创世纪 第二天

第二天,google说,荒芜要被开垦,系统便运作了,它是linux。               --xxx     荒蛮大地就要变得肥沃,linux已经运行起来了。。。。      linux就不多讲了,这里只讲讲被google大刀阔斧改了内核后的linux。      第一天最后,内核init已经干完了自己的事,把控制权交给了第一个用户级进程,也叫做init。      想知道这个init干了什么事,我们只能看看源码,不贴代码,这里只说说它干了什么。     (system/core/init/init.c -->main一、清空umask     也就是设置缺省权限,这里设置为0,umask为0000的话,就相当于chmod中的0777,经常使用linux对于chmod 777应该很熟悉,就是赋予某个文件的权限为,所有组、所有用户可读可写可运行,也就是最宽松的权限。 二、创建并挂载一些基本的目录      创建目录并挂载相应系统:        /dev   设备目录,所有的外围设备都在这里了,包括真实的设备如sim卡,也包括虚拟的设备如必不可少的null设备。挂载关系是 /dev -> tmpfs,tmpfs顾名思义就是临时文件系统,这个系统只占用内存空间。       /proc  系统信息目录,包含了当前系统的所有信息,比如进程、时钟等等动态的信息。挂载关系是 /proc -> proc        /sys  这里存储的东西,都是硬件设备在linux上映射的对象,比如pci设备。挂载关系是 /sys -> sysfs        /dev/pts  这个是远程终端控制台设备,字符终端啦,如果木有这个的话,就不可能adb shell调试android。挂载关系是 /dev/pts -> devpts        /dev/socket  服务于android的,socket是linux中进程通信的一种方式,/dev/socket下面就是已经被系统分配的soket资源,这里基本上是一些本地服务,比如ridl,有兴趣可以adb shell查看一下。 三、初始化NULL设备,重定向标准输入输出,初始化kmsg系统,并且解析init.rc文件      null是Linux的一个标准设备,也就是所谓的黑洞,至于为什么有它,就得从输入输出重定向说起,比如linux控制台下运行一个程序,有时会输出一大堆东西,这是它向标准输出写的,我们不想让它显示出来,就是用 > NULL给它的输出重定向到了这个黑洞设备,系统呢会给这个程序返回一个写入成功的操作,实质上,系统什么都木有干。      kmsg是linux下的一个内核级的日志系统,kernel message。就好比anroid提供的Log系统一样,只是针对内核级别的。      对于init.rc文件,这里只进行了解析,并没有执行里面的一些命令。 四、获得内核命令参数并且解析特定机型的init.*.rc文件      获得内核命令参数,也就是显式说明的一些参数,如果配置过grub或者Loli的话,就可能与这个打过交道。           每个手机硬件平台都不一样,adb shell一下,会发现有两个rc文件,其中一个就是与特定平台有关的rc配置文件,比如我的defy就是init.mapphone_umts.rc,为什么叫这个?中间就是手机硬件平台的名字,可以 cat /proc/cpuinfo来获得Hardware信息,我的如下:# cat cpuinfo cat cpuinfo Processor : ARMv7 Processor rev 2 (v7l) BogoMIPS : 299.11 Features : swp half thumb fastmult vfp edsp neon vfpv3 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc08 CPU revision : 2 Hardware : mapphone_UMTS Revision : 0000 Serial : 0000000000000000 CPU Tier : 10 可以看到Hardware的值就是rc的副名称。       init首先会获得/porc/cpuinfo中的这个属性值,然后根据这个字符串查找特定的rc文件,最后根据rc中的配置内容,解析它。 五、执行rc文件中的命令      上一步,init已经解析了那两个rc文件,这里,会根据rc文件中的具体内容,来分别执行对应的动作,后面会独立分析rc文件的格式内容,以及执行方法。 六、变为守护神        到这里,init就进入了死循环了for(;;){}。那么它都守护了些什么?       1、porpety service  启动并守护属性服务        android下特有的。就好比windows下面的注册表,记录了各种信息。大到系统是否成功运行的标志,小到短信声音。用户在设置一些手机设置的时候,在底层,实际就是和propety service打交道。        

属性前缀

描述

示例(shell下操作)

ro. 只读属性 setprop ro.media.capture.maxres 5m
摄像头的最大像素

persist.

额外存储到/data/property目录下 setprop persist.sys.country CN
不解释。注意,每个属性都存储为单独的一个文件 net. 联网相关,比如gprs、蓝牙…

setprop net.bt.name CAPF

蓝牙的网络名称为CAPF

net.change的值为最后一次更改net.*属性的属性名,例如:

net.change=net.gprs.local-ip

ctrl.start

控制命令

启动init.rc中标注为service的服务

setprop ctl.start bootanim

启动boot动态图像(第二屏启动画面)

一个服务设置后,其结果会以下面的属性返回,例如

init.svc.bootanim=running

ctrl.stop

停止init.rc中标注为service的服务

setprop ctl.stop bootanim

停止boot动态图像(第二屏启动画面)

一个服务设置后,其结果会以下面的属性返回,例如

init.svc.bootanim=stoped

        想要查看并设置属性,可以通过以下三种途径:    shell浏览文件:           /default.prop           /system/build.prop           /data/property/*    java:           System.getProperty(“xxxx”);           System.setProperty(“xxxx”);     c/c++:           demo.c:#include #include void print_prop(const char* key,const char* value,void* cookie) { printf("key=%s,value=%s/n",key,value); } int main() { property_list(print_prop,NULL); }            Android.mk:LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= / list_property.cpp / LOCAL_SHARED_LIBRARIES := / libcutils / libutils / LOCAL_MODULE:= list_prop include $(BUILD_EXECUTABLE) include $(call all-makefiles-under,$(LOCAL_PATH))     2、动态生成设备节点       android的linux下面是没有udev的,udev可以说是一个根据内核的硬件消息来自动发现设备的一个程序,android下面根据硬件相应的,也就是键盘与内存卡,在平板上面的话就更多了,比如鼠标、键盘等等。没有udev的话,android是如何实现硬件的热插拔呢?       和udev一样,init守护神同样监听了uevent事件,自己根据uevent的内容来做相应的事情,与udev做了异曲同工之事。       看一下大致流程。首先设备状态更改,内核会检测到,并发出uevent消息(字符串),init检测到消息,交给相应函数处理,这个函数根据uevent的内容,再做进一步处理。除了插拔内存卡等(android有专门的外存管理机制,就是vold),其它(比如数据线插入、鼠标插入)都会处理。     3、监听keychord事件       keychord是组合按键,从源码的行为来看,应该是考虑到组合键盘这种外设,大部分情况不会用到手机上,而多用在智能设备上,也就是没有触屏以及按键很少的android设备,比如运行android的手表神马的,通过不同的按键组合,来代表一个标准键盘的输入。       这个东东估计用的不多。     4、杀死僵尸进程       什么是僵尸进程?       linux的进程有个特点,一个主进程可以分裂(fork)子进程(android的受精卵zygote完美的发扬了这种精神),在桌面版的一些linux中,查看系统监视器,仔细看看进程信息,会发现很多进程会是树状结构,点击一个进程后面又展开了好几个进程,而且是个多级树。这都是一个进程有fork了好几个子进程的结果。       如果主进程被kill的话,那么它的子进程就有可能成为僵尸进程,所谓僵尸就是不干活但占用空间的程序死尸,这时,init守护神就负责回收这些无辜的灵魂,来释放本来就稀缺的内存资源。      5、守护重要服务        这些服务是native层面的服务,比如servicemanager、vold。例如重要的zygote,有时候(不经常)碰到的感觉和突然重启一样,这八成就是zygote崩溃并重启了,要知道java世界可是zygote孵化出来的。         解读init.rc       android的init.rc语法是独有的,可以说是一种语言吧。       init.rc的语法分为行为(Actions),命令(Commands) 、服务(Services)、选项(Options)(很多属性与命令用法都与linux中同名命令差球不多)       init是分段(section)解析init.rc的,在keywords.h中可以查看关键字的定义。init是以什么标志来分段解析init.rc呢?结合init.rc的内容,可以看出,分段标记是以on 和 service来标记的。下面详细说明。    on   啥时候干什么        on属于行为。      on early-init                init之前、加载完所有rc文件后即执行,在miui的rom中,init.rc在early-init执行的是start ueventd,根据keywords.h的定义,start是个命令(COMMAND)。             这里顺便说下ueventd,android中底层(一般指驱动)通知上层的事件,用的是uevent,java层通过观察者模式实现,用到的类为 UEventObserver,使用intent来传递;native层用的是android_os_UEventObserver.cpp,使用uevent.c通过socket传递。当然,这是framework及以下的层面,一般开发不经常用到,更何况这几个类都没有被暴露出来。      on init             加载propety各项属性文件之前执行,在init变为propety service之前都属于init阶段。                  on early-boot             启动属性服务后即执行。      on boot             boot的时候执行。      on property:xxxxx=x             当某个属性设置为预期值时执行。      关于init.rc,其实结合/src/system/core/init/* 源码和init.rc文件来看,会明白许多。水平有限,错误之处请指正,多谢!     创世纪:第一天连接:  创世纪:第三天连接:

相关内容推荐