Android Framework学习之跨进程通信方式
Android Framework用到了哪些IPC方式?
Linux IPC 方式
1.管道, 2. Socket, 3. 共享内存, 4. 信号
管道通信
半双工的,单向的,要么只能读,要么只能写,要想实现既能读又能写,管道得有两个描述符。linux API pipe(fds) 可以生成一对描述符,一个用来读,一个用来写。
一般是在父子进程之间使用(无名管道),如果是有名管道的话,只要两个进程知道这个管道的名字就可以通信了。
管道也可以用于同一进程
pipe(fd): 生成管道的一对描述符,fd[1]是用来写的,fd[0]是用来读的。fork出来的子进程会继承这个管道的一对描述符
close(fd[0]): 关闭父进程读描述符
close(fd[1]): 关闭子进程写描述符
java层Looper在native层对应的Looper,这是android4.4版本的代码,后面版本用的是EventFd
Looper里用到了管道
管道适用于数据量不大时的跨进程通信
Socket通信(非网络Socket)
全双工的,即可度也可写
两个进程之间无需存在亲缘关系
AMS与Zygote的通信就是用的Socket
main: Zygote 的入口函数
registerZygoteSocket:创建一个本地的Socket
Os.poll: 检测有没有我们关注的事件发生
runOnce:从Socket读取参数,根据参数执行相应的指令,主要是创建应用进程,进程创建完后,将pid写给对方
共享内存
很快,不需要多次拷贝(管道和Socket都不能传输大数据量,太大会导致性能下降,因它们涉及至少两次拷贝),通过文件描述符,把它同时映射到两个进程的内存空间,这样一个进程写,另一个进程就能读到
进程之间不用存在亲缘关系,只要能拿到文件描述符,文件描述符是可以跨进程传递的
共享内存主要用于大数据量的传递,比如图像相关的
MemoryFile是一个工具类, 封装了android 的 ashmem机制(匿名共享内存)
ashmem_create_region:在native层创建了一个快匿名共享内存
mmap:将描述符mFD映射到当前进程的一块内存空间,这个内存空间的地址是mAddress,
SetByteArrayRegion:将buffer的数据copy到java数组里
GetByteArrayRegion:将java层的数组 copy到native的buffer里
信号(需要root权限,或者与别的进程UID相同才能发信号)
单向的,发出去之后怎么处理是别人的事
只能带个信号,不能带别的参数
知道进程pid就能发信号了,也可以一次给一群进程发信号
应用进程都是Zygote fork出来的,uid与Zygote的uid一样,应用进程会马上修改uid
SetSigChildHandler:Zygote关注的SIGCHLD信号,Zygote启动了子进程后需要关注这个子进程退出了没有,如果退出了Zygote需要即使将其资源回收掉