parent
c2675c1f91
commit
089aef8bda
@ -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<eventCount;i++){ |
||||
int fd = eventItems[i].data.fd; |
||||
uint32_t epollEvents = eventItems[i].events; |
||||
if(fd == mWakeReadPipeFd){ |
||||
if(epollEvents&EPOLLIN){ |
||||
awoken(); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
``` |
||||
|
||||
管道在哪写的呢? |
||||
|
||||
```c++ |
||||
void Looper::wake(){ |
||||
nWrite = write(mWakeWritePipeFd, "W", 1); |
||||
} |
||||
``` |
||||
|
||||
##### Socket 通信 |
||||
|
||||
1. 全双工的,可读可写 |
||||
2. 两个进程之间无需存在亲缘关系 |
||||
|
||||
```java |
||||
public static void main(String argv[]){ |
||||
registerZygoteSocket(socketName); |
||||
runSelectLoop(abiList); |
||||
} |
||||
void runSelectLoop(String abiList){ |
||||
while(true){ |
||||
Os.poll(pollFds, -1); |
||||
for(int i=pollFds.length-1;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); |
||||
} |
||||
``` |
After Width: | Height: | Size: 408 KiB |
Loading…
Reference in new issue