Skip to content

Commit 02d97cc

Browse files
committed
update
1 parent 3d5dc96 commit 02d97cc

File tree

5 files changed

+99
-4
lines changed

5 files changed

+99
-4
lines changed

OperatingSystem/2.进程与线程.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@
293293
使用这个算法,调度程序总是选择剩余运行时间最短的那个进程运行。
294294

295295
- 轮转法
296-
296+
297297
一种最古老、最简单、最公平并且最广泛使用的算法就是轮询算法(round-robin)。每个进程都会被分配一个时间段,称为时间片(quantum),在这个时间片内允许进程运行。如果时间片结束时进程还在运行的话,则抢占一个 CPU 并将其分配给另一个进程。如果进程在时间片结束前阻塞或结束,则 CPU 立即进行切换。轮询算法比较容易实现。调度程序所做的就是维护一个可运行进程的列表,就像下图中的 a,当一个进程用完时间片后就被移到队列的末尾。
298298

299299
- 简单轮转: 就绪进程按FIFO排队,按照一定时间间隔让处理机分配给队列中的进程,就绪队列中所有队列均可获得一个时间片的处理器运行。
@@ -402,7 +402,7 @@ Linux为进程间通信和同步提供了各种机制。这里只是几种。
402402

403403
## Android进程结构
404404

405-
如同传统的Linux系统一样,Android的第一个用户空间进程是init,它是所有其他进程的根。然而,Android的init启动的守护进程是不同的,这些守护进程更多的聚焦于底层细节(管理文件系统和硬件访问),而不是高层用户设施,例如调度定时任务。Android还有一层额外的进程,它们运行Dalvik的Java语言环境,负责执行系统中所有以Java实现的部分。
405+
如同传统的Linux系统一样,Android的第一个用户空间进程是init(init的PID值是0),它是所有其他进程的根。然而,Android的init启动的守护进程是不同的,这些守护进程更多的聚焦于底层细节(管理文件系统和硬件访问),而不是高层用户设施,例如调度定时任务。Android还有一层额外的进程,它们运行Dalvik的Java语言环境,负责执行系统中所有以Java实现的部分。
406406

407407

408408

OperatingSystem/AndroidKernal/1.Android进程间通信.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,47 @@ SystemServer和Zygote之间通信不使用Socket的原因是为了要解决fork
221221

222222
在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。其中Service Manager和Binder驱动由系统提供,而Client、Server由应用程序来实现。其中,核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。Client、Server 和 ServiceManager 均是通过系统调用 open、mmap 和 ioctl 来访问设备文件 /dev/binder,从而实现与Binder驱动的交互来间接的实现跨进程通信。
223223

224+
如果统观Binder中的各个组成元素,就会惊奇的发现它和TCP/IP网络有很多相似之处:
225+
226+
- Binder驱动 -> 路由器
227+
- Service Manager -> DNS
228+
- Binder Client -> 客户端
229+
- Binder Server -> 服务端
230+
231+
TCP/IP中一个典型的服务连接过程(比如客户端通过浏览器方位Google主页):
232+
233+
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/binder_tcp_ip.png)
234+
235+
在这个简化的流程图中共出现了四种角色,即Client、Server、DNS和Router。它们的目标是让Client和Server建立连接,主要分为如下几个步骤。
236+
237+
- Client向DNS查询Google.com的IP地址。
238+
239+
显然,Client一定要先知道DNS的IP地址,才有可能向它发起查询。DNS的IP设置是在客户端接入网络前就完成了的,否则Client将无法正常访问域名服务器。当然,如果Client已经知晓了Server的IP,那么完全可以跨越这一步而直接与Server连接。比如Windows操作系统就提供了一个hosts文件,用于查询常用网址域名与其IP地址的对应关系。当用户需要访问某个网址时,系统会先从这个文件中判断是否已经存在有这个域名的对应IP。如果有就不需要再大费周折地向DNS查询了,从而加快访问速度。
240+
241+
- DNS将查询结果返回Client。
242+
243+
因为Client的IP地址对于DNS也必须是可知的,这些信息都会被封装在TCP/IP包中。
244+
245+
- Client发起连接。
246+
247+
- Client在得到Google.com的IP地址后,就可以据此来向Google服务器发起连接了。
248+
249+
在这一些列流程中,我们并没有特别提及Router的作用。因为它所担负的责任是将数据包投递到用户设定的目标IP中,即Router是整个通信结构中的基础。
250+
251+
从这个典型的TCP/IP通信中,我们还能得到什么提示呢?
252+
253+
首先,在TCP/IP参考模型中,对于IP层及以上的用户来说,IP地址是他们彼此沟通的凭证,任何用户在整个互联网中的IP标志符都是唯一的。
254+
255+
其次,Router是构建一个通信网络的基础,它可以根据用户填写的目标IP正确的把数据包发送到位。
256+
257+
最后DNS角色并不是必需的,它的出现是为了帮助人们使复杂难记的IP地址与可读性更强的域名建立关联,并提供查询功能。而客户端能使用DNS的前提是它已经正确配置了DNS服务器的IP地址。
258+
259+
Binder的本质目标用一句话来描述,就是进程1(客户端)希望与进程2(服务端)进行互访。但因为它们之间是跨进程(跨网络)的,所以必须借助于Binder驱动(路由器)来把请求正确投递到对方所在进程(网络)中。而参与通信的进程们需要持有Binder“颁发”的唯一标志(IP地址)。和TCP/IP网络类似,Binder中的DNS也并不是必需的,前提是客户端能记住它要访问的进程的Binder标志(IP地址)。而且要特别注意这个标志是动态IP,这就意味着即使客户端记住了本次通信过程中目标进程的唯一标志,下一次访问仍然需要重新获取,这无疑加大了客户端的难度。DNS的出现可以完美的解决这个问题,用于管理Binder标志与可读性更强的域名间的对应关系,并向用户提供查询功能。既然Service Manager是DNS,那么它的IP地址是什么呢? Binder机制对此作了特别规定,Service Manager在Binder通信过程中的唯一标志永远都是0.
260+
261+
262+
263+
264+
224265
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/binder_framework.png)
225266

226267
- Server

OperatingSystem/AndroidKernal/6.屏幕绘制基础.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,50 @@ Android的屏幕绘制架构如下图:
3939
- 每个具体的Drawable对象仅仅绘制某个特定的图案,SDK中包含的Drawable实现类有BitmapDrawable、NinePatchDrawable等。
4040

4141

42+
43+
Linux内核提供了统一的framebuffer显示驱动。设备节点/dev/graphics/fb*或者/dev/fb*,其中fb0表示第一个Monitor,当前系统中只用到了一个显示屏。
44+
45+
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/android_surface_flinger.png)
46+
47+
Android的HAL层提供了Gralloc,包括fb和gralloc两个设备。前者负责打开内核中的framebuffer、初始化配置,并提供了post、setSwapInterval等操作接口。后者则管理帧缓冲区的分配和释放。这就意味着上层元素只能通过Gralloc来间接访问帧缓冲区,从而保证了系统对framebuffer的有序使用和统一管理。
48+
49+
另外,HAL层的另一重要模块是“Composer”,如其名所示,它为厂商自定制“UI合成”提供了接口。Composer的直接使用者是SurfaceFlinger中的HWComposer,后者除了管理Composer的HAL模块外,还负责VSync信号的产生和控制。VSync则是Project Butter工程中加入的一种同步机制,它既可以由硬件产生,也可以通过软件来moni(VsyncThread)。
50+
51+
52+
53+
Framebuffer是系内核系统提供的图形硬件的抽象描述。之所以称为buffer,是因为它也占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。由此可见,在一切都是文件的Linux系统中,Framebuffer被看成了终端显示设备的化身。
54+
55+
另外,Framebuffer借助于Linux文件系统向上层应用提供了统一而高效的操作接口,从而让用户空间中运行的程序可以在不做太多修改的情况下去适配多种显示设备,无论它们属于哪家厂商、什么型号,都由Framebuffer内部来兼容。
56+
57+
在Android系统的GUI设计理念中,提供了两种本地窗口:
58+
59+
- 面向管理者(SurfaceFlinger)
60+
61+
既然SurfaceFlinger扮演了系统中所有UI界面的管理者,那么它无可厚非需要直接或间接地持有“本地窗口。这个窗口就是FramebufferNativeWindow。
62+
63+
- 面向应用程序
64+
65+
这类本地窗口是Surface。
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
4286

4387
---
4488

OperatingSystem/AndroidKernal/8.WindowManagerService简介.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ WmS是Android中图形用户接口的引擎,它管理着所有窗口,包括
1313
- 保持窗口的层次关系,以便SurfaceFlinger能够据此绘制屏幕
1414
- 把窗口信息传递给InputManager对象,以便InputDispatcher能够把输入消息派发给和屏幕上显示一致的窗口。
1515

16+
17+
18+
打个比方,就像一出由N个演员参与的话剧:SurfaceFlinger是摄像机,WMS是导演,ViewRoot则是演员个体。摄像机(SurfaceFlinger)的作用是单一而规范的,它负责客观地捕获当前的画面,然后真是的呈现给观众。导演(WMS)则会考虑到话剧的舞台效果和视觉美感,如他需要根据实际情况来安排各个演员的排序站位,谁在前谁在后,都会影响到演出的”画面效果“与”剧情编排“,而各个演员的长相和标清(ViewRoot)则更多的取决于他们自身的条件与努力。正式通过这三者的”各司其职“,才能最终为观众呈现出异常美妙绝伦的”视觉盛宴“。
19+
1620
Android采用层叠式布局,这种布局的特点在于允许多个窗口层叠显示。该布局一般都需要一个窗口管理服务端。从程序设计的角度看,有两种设计模式可以实现服务端:
1721

1822
- 独立进程方式

SourceAnalysis/Activity启动过程.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,9 +1496,15 @@ final void startActivityLocked(ActivityRecord r, boolean newTask,
14961496

14971497
在Android应用程序框架层中,是由ActivityManagerService组件负责为Android应用程序创建新的进程的,它本来也是运行在一个独立的进程之中,不过这个进程是在系统启动的过程中创建的。
14981498
ActivityManagerService组件一般会在什么情况下会为应用程序创建一个新的进程呢?当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程了,
1499-
然后在这个新的进程中启动这个Activity或者Service
1499+
然后在这个新的进程中启动这个Activity或者Service。
1500+
1501+
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/ams_start_activity.png)
1502+
1503+
无论以什么方式发起一个Activity的启动流程,最终都会调用到AMS的startActivity的函数。而在AMS真正启动一个Activity之前,需要经过众多烦琐的判断和准备工作,这些工作在AMS内部都是由一些列以startActivity开头的函数来进行逐步处理的。
1504+
1505+
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/activity_start_binder.png)
1506+
15001507

1501-
15021508
---
15031509

15041510
- 邮箱 :charon.chui@gmail.com

0 commit comments

Comments
 (0)