Android从BIOS到Zygote到SystemService到Launcher启动概况

来源:互联网 发布:沈阳市软件工资 编辑:程序博客网 时间:2024/06/05 19:54

不想当将军的士兵不是好的士兵,作为Android开发 肯定好奇手机启动到运行经历了什么。最近有点时间,所以看了几本书。有《LINUX SYSTEM PROGRAMING》、《Android源码分析实录》。
只写流程和重要的几个点。代码都可以在《Android源码分析实录》上找到,太多我就不写了。

开机第一个程序BIOS:
BIOS程序启动,检查硬件。
BIOS是烧在主板上上的只读程序,叫做韧体。硬件的信息记录在CMOS(记录各种硬件参数且嵌入在主板上面的存储器)。
BIOS到硬盘读取第一个扇区的MBR(主引导分区块)。MBR存储了引导加载程序(BootLoader)

操作系统第一个程序BootLoader
引导加载程序BootLoader,用于加载系统的内核文件。是操作系统安装在MBR上的一套软件。

内核运行的第一个进程 init进程
pid为1。系统查找init程序的默认顺序(除非用户通过init内核命令指定)

  1. /sbin/init
  2. /etc/init
  3. /bin/init
  4. /bin/sh Bourne shell程序的位置

如果都没有找到,就会挂起系统(halt system with a panic)

Zygote进程
init进程启动中解析init.rc文件,其中有

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd

解析的代码是在system\core\init\init.c 的service_start方法
init进程执行 系统调用 (System call,从应用程序发起 进入到内核的函数,为了从操作系统获取 服务或资源) fork(生成新进程)、execve (加载程序到内存地址,并替换为当前进程的地址空间)zygote程序。
从而运行了zygote进程,代码是在/system/bin/app_process

(fork 从当前进程生成子进程,新进程执行方法的栈不变。通过返回值区分那个进程,0是子进程,父进程是自己的pid。exec系列的调用 子进程就不在当前的方法栈中执行了,而是直接在新程序的方法中执行)

void testFork() {    pid_t pid;    pid = fork();    if (pid > 0)        printf("I am the parent of pid = %d!\n", pid);    else if (!pid)        printf("I am the child");    else if (pid == -1)        perror("fork error");}

扫描文件发现socket选项
为zygote进程创建Socket。调用函数create_socket在/dev/socket目录下创建文件。create_socket中System call函数socket,返回一个文件描述符,保存到环境变量中。

Linux系统最重要的抽象概念 文件(其次是进程),Linux遵循 everything is a file的理念。除了普通文件,Linux支持四种特殊文件: 字符设备文件(键盘)、 快设备文 件(硬盘、CD)、命名管道(Named pipes)和Unix域套接字(Unix domain sockets)
所以socket也是文件,还有Android中的Binder、Ashmem(匿名共享内存)都是创建一个文件,获取文件描述符,然后进行读取、增删改等操作。举例/dev/socket/zygote;/dev/binder; /dev/ashmem; Binder就是打开binder文件,通过 System call函数mmap把设备内存映射到 用户进程地址空间。然后相当于两个进程,共同操作一个文件,来达到IPC。

Zygote进程中的操作(入口函数在frameworks\base\cmds\app_process\app_main.cpp):

  1. fork出SystemServer进程,用于启动Android各项服务
  2. 创建虚拟机
  3. 注册JNI方法
  4. 连接前文中创建的Socket
  5. 最后无限循环等待socket连接。

ActivityManagerService收到startActivity的IPC调用后,经过N个方法的调用,判断目标Activity是否要在新的进程。如果是,通过startProcessLocked 生成LockSocket对象 去连接Zygote进程。Zygote收到读取参数,fork出应用进程,反射ActivityThread的main方法。最终应用进程的ActivityThread 初始化Looper,信息队列无限循环,用于接收 点击事件、Activity切换了各种Message。

SystemServer进程
Android最主要的两个进程 Zygote和SystemService。其中SystemService是Zygote fork出的第一个进程。fork后的操作:

  1. 关闭Socket服务端(因为fork出的子进程和父进程 共享文件,所以也持有Zygote的socket资源)
  2. 执行com.android.server.SystemServer类中的main()函数

Android绝大多数的Service(ActivityManagerService, WindowManagerService, PackageManagerService, InputManagerService)都是以线程的形势存在于SystemService中。

Android服务如图:

Android各个服务架构

第一个Activity
ActivityManagerService(AMS)的启动最后调用systemReady(),systemReady启动task顶部Activity,因为mMainStack队列还没有Activity对象,导致ActivityStack调用startHomeActivityLocked()。startHomeActivityLocked()中发出一个category为CATEGORY_HOME的intent,从而启动Launcher应用。

然后Launcher调用PackageManagerService查询 应用程序的icon、应用名称,用户一点击 IPC到AMS,AMS socket连接到 Zygote进程,Zygote进程fork应用进程,进程内部反射 ActivityThread main, ActivityThread初始化Looper,通过Binder的子类ApplicationThread,和AMS等服务进行IPC通信

相关资料:
首先《Android源码分析实录》,亮点是深入到了 Linux内核层,我第一次看到讲Binder,详细到把Linux驱动的源代码给贴出来的。缺点也很明显了:偏底层,不像《Android开发艺术探索》、《深入理解Android内核设计》在FrameWork层可以明显的有好处。
《LINUX SYSTEM PROGRAMING》就是看Binder驱动哪里看不懂,然后借了一本读的。有个惊喜的收获是讲了很多概念,有种醍醐灌顶的感觉。像是Linux两大抽象概念 文件、进程,文件的特殊文件、进程的fork exec。进程通信的signal。感觉挺有意思的。

原创粉丝点击