不想当将军的士兵不是好的士兵,作为Android开发 肯定好奇手机启动到运行经历了什么。最近有点时间,所以看了几本书。有《LINUX SYSTEM PROGRAMING》、《Android源码分析实录》。
只写流程和重要的几个点。代码都可以在《Android源码分析实录》上找到,太多我就不写了。
开机第一个程序BIOS:
BIOS程序启动,检查硬件。
BIOS是烧在主板上上的只读程序,叫做韧体。硬件的信息记录在CMOS(记录各种硬件参数且嵌入在主板上面的存储器)。
BIOS到硬盘读取第一个扇区的MBR(主引导分区块)。MBR存储了引导加载程序(BootLoader)
操作系统第一个程序BootLoader
引导加载程序BootLoader,用于加载系统的内核文件。是操作系统安装在MBR上的一套软件。
内核运行的第一个进程 init进程
pid为1。系统查找init程序的默认顺序(除非用户通过init内核命令指定)
- /sbin/init
- /etc/init
- /bin/init
- /bin/sh Bourne shell程序的位置
如果都没有找到,就会挂起系统(halt system with a panic)
/2021-10-25补充 Ubuntu系统/
- 如果是Ubuntu的话,pid 1的进程是systemd,然后用systemctl或service,就可以管理系统服务。
- 比如启动apache,ftp, ssh等服务
Zygote进程
/2021-10-25补充/
- 补充下 Zygote进程开启了VM,加载了Android SDK。后续的APP进程都是zygote进程fork出来(就是copy了zygote的内存,再exe新的内存部分,所以SDKyecopy了,所以高效,不用再读磁盘了)。 所以之后APP才能用 binder机制通信(近期面试题经常有,为啥zygote、system不用binder,而是 unix name socket。因为Android SDK还没初始化呗)
init进程启动中解析init.rc文件,其中有
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart 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):
- fork出SystemServer进程,用于启动Android各项服务
- 创建虚拟机
- 注册JNI方法
- 连接前文中创建的Socket
- 最后无限循环等待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后的操作:
- 关闭Socket服务端(因为fork出的子进程和父进程 共享文件,所以也持有Zygote的socket资源)
- 执行com.android.server.SystemServer类中的main()函数
Android绝大多数的Service(ActivityManagerSe