安卓之启动-初析(四)

12 篇文章 1 订阅
9 篇文章 0 订阅

补充总结

         有源代码的好处就是让我们能够通过读取源代码而了解一个可执行的最小单元的逻辑流程,但是大家都会经常犯一个错误,当然也包括我自己,那就是一旦我们自己拿起了代码,就深陷进了代码跳来跳去的泥潭了。一旦陷入了这个深渊,即使我们熟读代码,也很难和真正的“事实”(流程本身,逻辑本身等)联系起来。所以建议大家应该先对“事实”有个了解在去读代码,可是你要问我了,要是知道了这个“事实”还需要读代码嘛,恩,确实不需要,所以这个“事实”或许你知道,或许你需要去按照实际情况去猜

         举个例子吧:

    当我兴冲冲的读完了init程序相关的代码时,我看到了执行命令的方式都是通过调用main函数,输入相关参数执行的。但是我却找不到它们之间的关联,main啥时候被调用,于是我在代码中找呀找找要找,还是找不到。例如从init中我看到了zygote的启动,于是我去看zytoge的代码,不过我还看不到关联。我陷入了迷茫。

         想必大家都遇到过这种小错误,那问题出在哪里呢,就是出自你在看代码的时候忘记了“事实”。让事实和真实断开了。

         在阐述这个事实之前我先像大家在介绍一下linux相关的东西:

         守护进程,它在系统自举时启动,仅在系统关闭时停止,它们不会控制终端,之后再后台运行,负责处理日常进程。init的一个功能就是开启这些守护进程。

         linux shell,一个可以用来通过传递命令和参数与内核打交道的工具,通过这个shell你可以执行自己的程序,执行一些你想执行的程序,甚至可以通过向这个shell发送数据来执行程序。

         init程序在系统上实际上一定是一个编译好的可执行文件(excuteable file),并且其他大部分需要启动的服务都是编译好的可执行文件。被放到了相关的目录下。

         ok知道这些就够了,其实大家都知道,但是可能从来都没有和真实联系在一起。

    好那现在看一下“事实”:

    有一个程序它包含 A B C D E 个执行体(都是可执行文件),执行流程是:

    A ----|-----B  |____D------E

            |-----C  |

     程序先执行A,之后B、C几乎同时执行,B、C执行完毕后执行D,D执行完毕后执行E,流程结束。

我们假设A就是Linux Kernel,B是进程ID为0的调度进程叫做swaper,C为进程ID为1的进程叫做init,我们叫D为servicemanager,E为特定的Servcie。

和“事实”的关系:

A--对应于linus他们发布的linux某个版本的源码编译后的内核文件。

B--对应于内核之中的一个可执行程序,调度进程。

C--init对应于/sbin/init,是由/system/core/init/下文件编译成的可执行文件。

D--servicemanager对应于/system/bin/servicemanager,是由framework/base/servicemanager下相关文件编译的可执行程序。

E--对应于framework各种service编译后可执行文件。

上面已经讲到了linux的守护进程,和基于shell和内核通讯的机制,并且知道了init会初始化这些守护进程。

ok,现在让我们来阐述一下“事实”,但是阐述的时候要抛离开代码:

好,A(内核加载)启动了,紧接着A启动完毕,A要求B(swaper)和C(init)马上启动干活,C知道它启动后要负责D(servicemanager)启动,而且D的启动会引起E(各种真正service)的相关启动。

事实既然如此,执行设置好约定,什么时候调用什么可执行文件就可以了,纯净的系统怎么会有源代码呢对吧(可能有但无关紧要)。你让我关闭热水器,我关闭就是了,它就在那里,我干嘛需弄清楚它是怎么做的,我又不是生产热水器的厂商。所以你别拉我进入那个泥潭。

好,寻找“事实”:

某一天热水器(犹如init,app_process这样的可执行程序)坏了(或者我想对我的热水器进行我自己的人工升级),而且过了保修期,巧合我得到了一份关于热水器详细生产和使用说明书(犹如原代码)。我自信的研读这些,终于知道了它的原理(init可执行程序的流程,通过研读相关源代码),修好了它。

好转了一圈,弄清楚了吗,在思考问题的时候要先去想一下“事实”,我们通过已经了解的知识有这个能力了解了事实,在去读真实的代码,就不会在乱套了。

你问我zygote怎么运行的,我以事实回答你的问题。首先init启动,启动过程它要依赖init.rc文件,它找到了service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 这句,然后它通过解析发现它是readme.txt提到的service 后面是service名称zygote,它是位于/system/bin/的可执行文件app_process 并且带有一些参数,并且它同时用/system/bin 通过zygote启动了一个system-server。那这一行只是一个文本,它可不会执行哦,对的,现在需要将它通过shell或者其他通讯方式传给后端或者内核执行了。好,手工。

你明白这个事实了嘛,ok找源代码也不在话下了吧,好,我们要通过这种方式去读代码,要不很容易陷入代码的深渊里,而忘了读属于谁的代码,执行什么逻辑。

init流程是以上事实的集合,什么启动后台守护进程了,建立相应文件系统,建立驱动文件映射,打开某些驱动,设置相应权限,设置一些共享变量,启动用户级进程,设置网络,还真多呢……

还有一点需要注意的地方,就是init在执行的过程中驱动相关呀、adb相关、servicemanagerservice相关、zygote相关、system application 相关都已经伴随着init一起启动了,可想而知它们的和构成了init的流程,而不是init完成之后,zygote等才启动。

 unix 一切皆文件  ,这个文件系统和 VFS 文件系统稍稍不同 ,但是有些需要vfs提供支持, 所以驱动程序呀、硬件呀、硬件信息呀、都需要以文件方式挂载 并挂载在VFS的文件系统上 ,有些文件例如/proc下的一般都在内存中 ,那么我们在用户空间  就可以访问这些文件来达到访问硬件和驱动的目的了。 另外shell 提供了我们与内核交互的功能,所以 init 做了这些工作,为我们事后访问内核与内核交互提供了保障,至于非内核空间的东西  我们以普通方式访问 就是了。  这是我讲init 没有提到的 。记住挂载文件系统 和建立驱动设备 硬件等文件映射 是一定要做的 ,我们看到的linux 是启动后的 文件系统已经mount  ,而且每次启动都要去执行这些操作 每次都要去mount ,而且 向那些设备驱动文件 本身是不存在的  关机之后 就消失了  ,切记。每次都mount ,所以init.rc里有那么多的mount

此是初版,后期会进行更正。请斧正。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值