Android开机流程linux
当按开机键的时候,引导芯片开始从固化在ROM的预设代码开始执行,而后加载引导程序到RAM
BootLoader,又称为引导程序。它是在操做系统运行以前运行的一段程序
BootLoader负责初始化软件运行所须要的最小硬件环境,最后加载内核到内存android
这个入口的函数是start_kernel函数
start_kernel函数执行到最后调用了reset_init函数进行后续的初始化
start_kernel最终启动用户空间的init程序windows
当初始化内核以后,init进程负责解析init.rc配置文件, 就会启动一个至关重要的祖先进程,也就是init进程,在Linux中全部的进程都是由init进程直接或间接fork出来的架构
* /system/bin/app_process_Zygote服务启动的进程名 * --start-system-server 代表Zygote启动完成后,须要启动System_Server进程 * socket zygote stream 666在Zygote启动时,建立一个权限为666的socket。此socket用来请求zygote建立新进程 * socket的fd保存在名称为"ANDROID_SOCKET_zygote"的环境变量中
init进程负责建立系统中最关键的几个核心daemon(守护)进程,尤为是zygote和System_Server进程app
1. zygote进程 android启动的第一个Dalvik 虚拟机,它将负责启动Java世界的进程 2. zygote虚拟机启动子进程system_server,同时也能够看出zygote中定义了一个Socket,绑定666端口,用于接收ActivityManagerService启动应用程序的请求 3. System_Server进程 Binder通讯的基础,它还提供了property service(属性服务),相似于windows系统的注册表服务 4. 系统里面重要的服务都是在这个进程里面开启的,例如AMS, WindowsManager, PackageManagerService等等都是由这个System_Server fork出来的 5. 在System_Server进程开启的时候,就会初始化ActivityManagerService 。同时,会加载本地系统的服务库,调用createSystemContext()建立系统上下文,建立ActivityThread及开启各类服务等等 6. system_server中开启了核心系统服务,并将系统服务添加到ServiceManager中,而后系统进入SystemReady状态
启动Home Activitysocket
概况 1. 系统加电,执行bootloader。Bootloader负责初始化软件运行的最小硬件环境,最后加载内核到内存 2. 内核加载到内存后,进入内核引导阶段,在内核引导的最后,调用start_kernel进入内核启动阶段。start_kernel最终启动用户空间的init程序 3. init负责解析init.rc配置文件,开启系统守护进程。2个最重要的守护进程是zygote进程和serverManager进程。zygote是android启动的第一个Dalvik虚拟机,ServiceManager服务是Binder通讯的基础 4. zygote虚拟机启动子进程system_server,在system_server中启动了核心系统服务,并将系统服务添加到ServiceManager中,而后系统进入SystemReady状态 5. 在SystemReady状态,ActivityManagerService与zygote中的socket通讯,经过zygote启动home应用,进入系统界面 * 从步骤3开始, init启动后,上层的实现 1. init启动的核心Daemon服务包括Android的第一个Dalvik虚拟机Zygote 2. zygote定义一个socket,用于接受ActivityManangerService启动应用的请求 3. zygote经过fork系统调用建立system_server进程 4. 在system_server进程中,将会启动系统核心服务以及其余服务 5. 系统服务启动后会注册到ServiceManager中,用于Binder通讯 6. ActivityManagerService进入systemReady状态 7. 在systemReady状态,ActivityManangerService会与zygote的Socket通讯,请求启动Home 8. zygote收到AMS的链接请求后,执行runSelectLoopMode处理请求 9. zygote处理请求会经过forkAndSpecialize启动新的应用进程,并最终启动Home
Message - Message表明一个行为what或者一串动做Runnable, 每个消息在加入消息队列时,都有明确的目标Handler ThreadLocal - 线程本地存储区(Thread Local Storage,简称为TLS),每一个线程都有本身的私有的本地存储区域,不一样线程之间彼此不能访问对方的TLS区域。ThreadLocal的做用是提供线程内的局部变量TLS,这种变量在线程的生命周期内起做用,每个线程有他本身所属的值(线程隔离) MessageQueue (C层与Java层都有实现) - 以队列的形式对外提供插入和删除的工做, 其内部结构是以双向链表的形式存储消息的 Looper (C层与Java层都有实现) - Looper是循环的意思,它负责从消息队列中循环的取出消息而后把消息交给Handler处理 Handler - 消息的真正处理者, 具有获取消息、发送消息、处理消息、移除消息等功能
普通的线程是没有looper的,若是须要looper对象,那么必需要先调用Looper.prepare方法,并且一个线程只能有一个looper
Handler是如何完成跨线程通讯的ide
* Android中采用的是Linux中的管道通讯 * 关于管道,简单来讲,管道就是一个文件 * 在管道的两端,分别是两个打开文件文件描述符,这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的 * 消息队列建立时,会调用JNI函数,初始化NativeMessageQueue对象。NativeMessageQueue则会初始化Looper对象 * Looper的做用就是,当Java层的消息队列中没有消息时,就使Android应用程序主线程进入等待状态,而当Java层的消息队列中来了新的消息后,就唤醒Android应用程序的主线程来处理这个消息
整个消息机制流程函数
Handler经过sendMessage()发送Message到MessageQueue队列 Looper经过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理 通过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理 将Message加入MessageQueue时,处往管道写入字符,能够会唤醒loop线程;若是MessageQueue中没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,每每用于作一些清理性地工做
Activity的window组成,Activity内部有个Window成员,它的实例为PhoneWindow,PhoneWindow有个内部类是DecorView,这个DecorView就是存放布局文件的,里面有TitleActionBar和咱们setContentView传入进去的layout布局文件oop
+ measure, 递归测量view的大小。有3种测量模式 - MeasureSpec.EXACTLY表示肯定大小 - MeasureSpec.AT_MOST表示最大大小 - MeasureSpec.UNSPECIFIED不肯定 + layout,递归布局view的位置 + draw,递归绘制view - ViewRootImpl中的代码会建立一个Canvas对象,而后调用View的draw()方法来执行具体的绘制
进程空间分配源码分析
Binder跨进程通讯(IPC)的原理
使用步骤:
注册服务
* Server进程向Binder驱动发起服务注册请求 * Binder驱动将注册请求转发给ServiceManager进程 * ServiceManager进程添加该服务 * 此时ServiceManager进程拥有该服务信息
获取服务
* Client向Binder驱动发起获取服务的请求,传递要获取的服务名称(service name) * Binder驱动将该请求转发给ServiceManager进程 * ServiceManager查找到Client须要的Server对应的服务信息 * 经过Binder驱动将上述服务信息返回给Client进程 * 此时client进程与server进程已经创建了链接
使用服务
* Client进程将参数数据发到Server进程 1. client 进程将须要的传送的数据放到client进程的共享内存;(当前线程被挂起) 2. Binder驱动从client的共享内存中读取数据,并根据ServiceManager进程里面的Server信息找到对应的Server进程 3. Binder驱动将数据copy到Server进程的共享内存里,并通知Server进程解包 * Server进程根据Client进程要求,调用目标方法 1. 接到Binder驱动通知后,Server进程从线程池中取出线程,进行数据解包和调用目标方法 2. 将最终方法结果写到本身的共享内存 * Server进程将目标方法的结果,返回给Client进程 1. Binder驱动程序将Server进程的共享内存里面的数据(方法执行结果) copy 到client进程的共享内存 2. 通知client进程得到返回结果(此时client进程以前被挂起的线程被从新唤醒)
Client进程、Server进程 & Service Manager 进程之间的交互 都必须经过Binder驱动(使用 open 和 ioctl文件操做函数),而非直接交互
Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互
Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互
Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(须要开发者本身实现)
每一个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例自己,value是真正须要存储的Object
android自己就是linux系统 因此查看命令和linux同样
dalvik.vm.heapstartsize 表示 初始内存大小是8m
dalvik.vm.heapgrowthlimit 表示标准内存大小是96m 通常应用都是这么大
dalvik.vm.heapsize 表示 在manifest配置文件中application标签下配置 android:largeHeap="true"时的内存大小
apk安装包大小理论上没有限制。可是各个应用商店为了有大小限制google play 要求小于50M , 扩展包能够扩展到2g
压测: 800M的apk是没问题的只是安装的时间比较长。1.6G的apk包则把手机弄死机
ThreadPoolExecutor构造函数的maximumPoolSize决定
ART 的机制与 Dalvik 不一样。在Dalvik下,应用每次运行的时候,字节码都须要经过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫作预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。
即整个应用的主线程,只有这一个looper,无论有多少handler,最后都会回到这里
public static void loop() { ... for (;;) { ... // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } ... } }
设置Printer对象,判断是否超过预期时间,notifyLog