10.2、android输入系统_必备Linux编程知识_双向通信(scoketpair)
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