diff --git a/blogs/Android/Framework/Interview/进程间通信相关/Framework IPC 方式汇总.md b/blogs/Android/Framework/Interview/进程间通信相关/Framework IPC 方式汇总.md new file mode 100644 index 0000000..8a0b38e --- /dev/null +++ b/blogs/Android/Framework/Interview/进程间通信相关/Framework IPC 方式汇总.md @@ -0,0 +1,149 @@ +--- +Android Framework 里面用到了哪些 IPC 方式? +--- + +1. 是否了解 Linux 常用的跨进程通信方式 +2. 是否研究过 Android Framework 并了解一些实现原理 +3. 是否了解 Framework 各组件之间的通信原理 + +#### Linux IPC 方式 + +1. 管道 +2. Socket +3. 共享内存 +4. 信号 + +##### 管道 + +1. 半双工,单向的 +2. 一般是在父子进程之间使用 + +![](https://i.loli.net/2020/03/27/UcCtmGaYMWRoseb.png) + +Framework 哪用到了管道? + +Looper 里面用到了管道: + +```c++ +Looper::Looper(bool allowNonCallbacks){ + int wakeFds[2]; + // 创建一个管道(4.4) + int result = pipe(wakeFds); + mWakeReadPipeFd = wakeFds[0]; + mWakeWritePipeFd = wakeFds[1]; + mEpollFd = epoll_create(EPOLL_SIZE_HINT); + struct epoll_event eventItem; + eventItem.events = EPOLLIN; + eventItem.data.fd = mWakeReadPipeFd; + epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); +} +``` + +epoll 是如何监听读端事件的? + +```c++ +int Looper::pollInner(int timeoutMillis){ + struct epoll_event eventItems[EPOLL_MAX_EVENTS]; + int eventCount = epoll_wait(mEpollFd, eventItems, ...); + for(int i=0;i=0;--i){ + if(i==0){ + // 处理新过来的连接 + }else{ + // 处理发过来的数据 + peers.get(i).runOnce(); + } + } + } +} +``` + +##### 共享内存 + +1. 很快,不需要多次拷贝 +2. 进程之间无需存在亲缘关系 + +涉及进程之间大数据量传输主要就是图像相关的了: + +```java +// 匿名共享内存 +public MemoryFile(String name, int length){ + mLength = length; + // ashmem_create_region(namestr, length); + // 创建一块匿名共享内存,返回一个 fd + mFD = native_open(name, length); + // mmap(NULL, length, prot, MAP_SHARED, fd, 0); + // 给这个 fd 映射到当前进程内存空间 + mAddress = native_mmap(mFD, length, PROT_READ|PROT_WRITE); +} +``` + +MemoryFile 的读和写: + +```java +// 把共享内存的数据读到应用进程的 buffer 里面 +jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, ...){ + env->SetByteArrayRegion(buffer, destOffset, count, ...); + return count; +} +// 把应用层的 buffer 拷贝到共享内存里面 +jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, ...){ + env->GetByteArrayRegion(buffer, srcOffset, count, ...); + return count; +} +``` + +##### 信号 + +1. 单向的,发出去之后怎么处理是别人的事 +2. 只能带个信号,不能带别的参数 +3. 知道进程 pid 就能发信号了,也可以一次给一群进程发信号 + +杀掉应用进程,需要用到信号: + +```java +public class Process{ + public static final void killProcess(int pid){ + sendSignal(pid, SIGNAL_KILL); + } +} +static void SetSigChldHandler(){ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.as_handler = SigChldHandler; + sigaction(SIGCHLD, &sa, NULL); +} +``` \ No newline at end of file diff --git a/images/Android/Framework/Interview/管道.png b/images/Android/Framework/Interview/管道.png new file mode 100644 index 0000000..b24a284 Binary files /dev/null and b/images/Android/Framework/Interview/管道.png differ