Android Framework用到了哪些IPC方式?

这道题想考察什么?

  • 是否了解Linux常用的跨进程通信方式
  • 是否研究过Android Framework并了解一些实现原理
  • 是否了解Framework各组件之间的通信原理

Linux IPC方式

  • 管道
  • Socket
  • 共享内存
  • 信号

管道通信

  • 半双工的,单向的
  • 一般是在父子进程之间使用
int main(void) {   
	int n, fd[2];   
	char buf[SIZE];   
	
	//生成一对描述符,一个用来写,一个用来读。
	pipe(fd);//生成一对管道描述符,fd[1]用于写,fd[0]用于读
	
	pid_t pid = fork();//fork调用创建了子进程,子进程会继承这一对管道描述符
	//想父进程往子进程中写东西
	if (pid == 0) {//子进程
		close(fd[1]);//将子进程的写的描述符关了    
		read(fd[0], buf, SIZE);//子进程就从读的描述符中将字符串读出来
	} else if (pid > 0) {//父进程 
		close(fd[0]); //将父进程的读的描述符关了     
		write(fd[1], "Hello", 5);//父进程往写的描述中写入一个字符串
	}
}

示意图如下:
在这里插入图片描述
父进程的读描述符fd[0]关闭,子进程的写描述符fd[1]关闭;
父进程的写描述符fd[1]写入数据,子进程的读描述符fd[0]读取数据。

FrameWork中的管道使用

//Android 6.0之前使用管道,之后使用eventfd
Looper::Looper(bool allowNonCallbacks) {    
	int wakeFds[2];
    int result = pipe(wakeFds);
    mWakeReadPipeFd = wakeFds[0];//读
    mWakeWritePipeFd = wakeFds[1];//写 
	
	...    
	
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);//创建epoll
    struct epoll_event eventItem;    
    eventItem.events = EPOLLIN;    
    eventItem.data.fd = mWakeReadPipeFd;    
    //监听读事件
    epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
}
int Looper::pollInner(int timeoutMillis) {    
	struct epoll_event eventItems[EPOLL_MAX_EVENTS];
	//epoll_wait阻塞等待事件,eventCount表示有几个事件被触发了
	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;
}
//写
void Looper::wake() {    
	nWrite = write(mWakeWritePipeFd, "W", 1);
}

管道和epoll结合,监听读写事件

管道:在数据量不怎么大的跨进程通信的时候使用

socket通信

  • 全双工的,既可读又可写
  • 两个进程之间无需存在亲缘关系(指定路劲)
//mian是Zygote的入口函数
public static void main(String argv[]) {   
  ......    
  //创建了ZygoteSocket
  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();            
	        }       
	    }    
   }
}

共享内存

  • 很快,不需要多次拷贝
  • 进程之间无需存在亲缘关系

进程间大数据量传输的,主要图像相关的

//工具类,封装了Android的Ashmem共享机制-匿名共享内存
public MemoryFile(String name, int length) {
    mLength = length; 
    mFD = native_open(name, length); 
    mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
}

native_open :ashmem_create_region(namestr, length);创建匿名共享内存
native_mmap:mmap(NULL, length, prot, MAP_SHARED, fd, 0);映射到当前进程的内存空间,内存空间的地址就是mAddress。

jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,) {   
  ……    
  env->SetByteArrayRegion(buffer, destOffset, count,);   
  ……    
  return count;
}
jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, ...) {
    …… 
    env->GetByteArrayRegion(buffer, srcOffset, count,);  
    ……    
    return count;
}

信号

  • 单向的,发出去之后怎么处理是别人的事
  • 只能带个信号,不能带别的参数
  • 知道进程pid就能发信号了,也可以一次给一群进程发信号
public class Process {
	//杀掉应用进程
    public static final void killProcess(int pid) {      
    	sendSignal(pid, SIGNAL_KILL);//发送SIGNAL_KILL信号
    }
}
static void SetSigChldHandler() { 
   struct sigaction sa;  
   memset(&sa, 0, sizeof(sa));   
   sa.sa_handler = SigChldHandler;
   
   //Zygote关注的信号
   //Zygote启动子进程后,要关注子进程是否退出
   sigaction(SIGCHLD, &sa, NULL);
}

总结

  • 先列举用到了哪些IPC方式
  • 说一说这些IPC方式的特点
  • 举例说明Framework里怎么用到的
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值