2. 双向通信(socketpair)

输入系统肯定涉及进程通讯:进程A读取/分发输入事件,APP处理输入事件,进程A给APP发送输入事件,APP处理完事件回复信息给进程A,APP关闭的时候也要发信息给进程A

binder用在进程间双向通信的时候的确定:每次请求只能由client单方发起

因此如果使用binder来实现双向通信,client也要提供server功能,server也要提供client功能

这里引入socketpair,其实现原理如下:

APP调用socketpair对得到两个文件句柄fd1和fd2:

fd1和fd2在内核空间中有两个buf,send_buf1、send_buf2和rcv_buf1、rcv_buf2,应用程序通过fd1把数据写到send_buf1,内核里的socketpair会把send_buf1的数据写入rcv_buf2,同理数据也可以主动从send_buf2到rcv_buf1

socketpair的缺点是其只适应于线程间通信或者有亲缘关系的进程,比如父子进程间通信,因为fd1和fd2又调用socketpair的进程创建,不能被其他进程得到;因此这个时候如果还有一个APP2如果想和APP1双向通信,怎么办?

利用binder得到fd2,在APP2中这个文件句柄是fd3,就可以和fd1通信了

参考代码:
frameworks\native\libs\input\InputTransport.cpp (socketpair)
调用过程
WindowManagerService.java
  InputChannel.openInputChannelPair(name)
    nativeOpenInputChannelPair(name);
      android_view_InputChannel_nativeOpenInputChannelPair
        InputChannel::openInputChannelPair (InputTransport.cpp)

socketpair.c

#include <pthread.h>

#include <unistd.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#define SOCKET_BUFFER_SIZE (32768U)

void *function_thread1(void *arg)

{

  int fd = (int)arg

  while(1){

    /*向main线程发出,hello,main thread*/

    len = sprintf(buf,"hello,main thread,cnt = %d",cnt++);

    write(fd,buf.len);

    /*读取数据(main线程发回的数据)*/

    len = read(fd,buf,500);

    buf[len] = '\0'

    printf("%s\n",buf);

    sleep(5);

  }

  return NULL;

}

int main(int argc,char **argv)

{

  int sockets[2];

  socketpair(AF_UNIX,SOCK_SEQPACKET,0,sockets);

  //给fd1和fd2创建sendbuf和rcvbuf

  int bufferSize = SOCKET_BUFFER_SIZE;

  setsockopt(sockets[0],SOL_SOCKET,SO_SNDBUF,*bufferSize,sizeof(bufferSIze));

  setsockopt(sockets[0],SOL_SOCKET,SO_RCVBUF,*bufferSize,sizeof(bufferSIze));

  setsockopt(sockets[1],SOL_SOCKET,SO_SNDBUF,*bufferSize,sizeof(bufferSIze));

  setsockopt(sockets[1],SOL_SOCKET,SO_RCVBUF,*bufferSize,sizeof(bufferSIze));

  /*创建线程1*/

  pthread_t threadID;

  pthread_create(&threadID,NULL,function_thread1,(void *)sockets[1]);

  char buf[500];

  int len;

  int cnt = 0;

  int fd = sockets[0];

  while(1){

    /*读数据:线程1发出的数据*/

    len = read(fd,buf,500);

    buf[len] = '\0'

    printf("%s\n",buf);

    /*main thread向thread1发出:Hello,thread1*/

    len = sprintf(buf,"hello,thread1,cnt = %d",cnt++);

    write(fd,buf.len);

  }

}

测试:
gcc -o socketpair socketpair.c -lpthread
./socketpair

最新文章

  1. C++ tinyXML使用
  2. C#winForm调用WebService的远程接口
  3. 第2章 Linux系统安装(1)_VMware安装与使用
  4. 【笔记6】用pandas实现条目数据格式的推荐算法 (基于物品的协同)
  5. 十大经典排序算法总结——JavaScrip版
  6. 在Android上实现使用Facebook登录(基于Facebook SDK 3.5)
  7. 【Objective-C】2.自定义构造方法和description方法
  8. [每日一题] 11gOCP 1z0-052 :2013-09-1 RMAN-- repair failure........................................A20
  9. Buy the Ticket HDU 1133 递推+大数
  10. [Protractor] Getting Started With Protractor
  11. IE浏览器下ajax和缓存的那些事儿
  12. shell 中let无法使用的原因
  13. hdu 1238 Substrings(kmp+暴力枚举)
  14. Kafka技术内幕 读书笔记之(六) 存储层——日志的读写
  15. xtrabackup备份还原MySQL数据库
  16. 惊世骇俗的sql语句之连表查询
  17. solr的基本使用
  18. JavaScript DOM 元素属性 状态属性
  19. JS类、对象、方法、prototype、_proto_
  20. Shell 单行注释和多行注释

热门文章

  1. tomcat+nginx+redis实现均衡负载以及session共享
  2. 怎样及时检测出非正常断开的TCP连接(zz)
  3. android学习笔记五。1、Service深入学习
  4. [ Java ] [ Eclipse ] 加速 Eclipse 載入速度-轉載
  5. Gym 100952 A. Who is the winner?
  6. linux命令行打开图片
  7. ZJOI2017线段树
  8. Pig源代码分析: 简析运行计划的生成
  9. ThreadLocal使用演示样例
  10. VPS 上线监控监控脚本