Android很多地方会涉及到进程间的通信,比如输入系统,那么进程间通信会涉及哪些内容呢?
1、进程:负责读取和分发事件
2、应用程序:负责处理输入事件
上面这两个进程会涉及哪些双向通信呢:
1.进程会发送输入事件
2.应用程序会告知事件处理完或APP已关闭
这里大家可能会有疑惑,binder系统能否实现上面所说的双向通信呢?
答案是不行,binder分为server和client,每次都由client主动发出请求,server收到请求后进行答复,这样的缺点就是每次请求只能单方发起,server不能主动发送数据给client,这样自然不能称为双向通信。
所以这里引入一个新的方法,叫“socketpair”
APP通过socketpair调用得到两个文件句柄,假设这两个文件句柄是fd1和fd2,这两个文件都对应有两个缓冲区(send_buf、rcv_buf),当某个进程或线程通过fd1写到他的send_buf的时候,内核里面的socket就会把send_buf里面的数据写到fd2的rcv_buf里面,另外一个线程或进程就可以读取fd2得到那些数据了,相反同理。
但是它也有缺点:由于是通过创建文件句柄来访问句柄实现的通信,那么谁可以看到这个句柄呢,只有当前APP创建出来的线程或它创建出来的子进程才能看到这些文件句柄,所以只适用于线程间通信,或者具有亲缘关系(父子进程)的进程间通信。
那么如果想使用socketpair来实现任意间的进程间的双向通信怎么办?
假设现在有APP1和APP2,这两个APP想进行任意间的进程通信,那么APP2需要得到APP1的fd2才行,怎么得到呢?可以通过binder通信,把fd2传给APP2,当然在APP2里面它就变为fd3了,这样这个任意的进程APP2就可以通过socketpair来进行通信了。这篇暂不讲解binder的实现方式
下面讲解一下“Socketpair”的程序及使用:
#include <pthread.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #define SOCKET_BUFFER_SIZE (32768U) /* 参考: * frameworks\native\libs\input\InputTransport.cpp */ /* 线程1函数实现 */ void *function_thread1 (void *arg) { int fd = (int)arg;/* 把文件句柄转换出来 */ char buf[500]; int len; int cnt = 0; 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); /* 延时5秒钟 */ sleep(5); } return NULL; } int main(int argc, char **argv) { int sockets[2]; /* 使用 socketpair 得到两个文件句柄到数组sockets */ socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets); /* 设置缓冲区, 每个文件句柄对应两个缓冲区,两个文件对应四个 */ 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(thread1),并把文件句柄sockets[1]传给子线程thread1 */ pthread_t threadID; pthread_create(&threadID, NULL, function_thread1, (void *)sockets[1]); char buf[500]; int len; int cnt = 0; int fd = sockets[0];/* 当前main函数的文件句柄是sockets[0] */ while(1) { /* 读数据: 读html" target="_blank">线程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); } }
程序非常简单,先是使用socketpair得到两个文件句柄并设置发送接收缓冲区,然后创建另一个线程,在线程中通过文件句柄读写数据到main线程中,mian也执行同样的操作实现双向通信。
测试验证:
检查是否存在这两个线程:
我们还可以修改程序,让应用程序fork出一个子进程,然后让父子进程通过socketpair来实现双向通信,比较简单,这里就不细讲了。
由于socekpair只适用于线程间通信,或者具有亲缘关系,如果想实现任意的两个进程间的双向通信就需要使用binder系统把fd传给另一个进程,这里简单说下过程,如下:
使用binder传输文件句柄:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
大家好,我有以下问题。我有一个扫描仪,我正在用命令和接收一些行。目前,我尝试到目前为止与超级终端,这是完美的工作。但是现在我的程序中需要这些代码行,所以我设置了Java Comm API和RXTX(只是因为我不能让它与Comm API一起工作)。 我已经在论坛上读了很多,但我不能把它发挥作用。 有人能帮帮我吗?非常感谢你的努力
描述 (Description) 此函数使用PROTOCOL在指定TYPE的指定DOMAIN中创建一对未命名的连接套接字。 如果未实现系统socketpair()函数,则会导致致命错误。 语法 (Syntax) 以下是此函数的简单语法 - socketpair SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL 返回值 (Return Value) 失败时此函数返回
正在开发一个新产品,该产品将使用ESP8266、Xamarin应用程序和Azure IoTHub为客户的设备启用双向通信。 我们有C2D(云2设备)和D2C(设备2云)通信在应用程序和电除尘器上正常工作,但是我们没有找到任何关于设置IoTHub来解释传入的遥测消息、处理它们各自的“到:”字段并将它们回到C2D主题,这应该允许我们的目标设备接收它。 我们的尝试: 逻辑应用。能够触发进入队列的消息,但
在深入了解WebSocket的需求之前,有必要先了解一下现有的技术,这些技术用于服务器和客户端之间的双工通信。这些技术如下 - 轮询 长轮询 数据流 回发和AJAX HTML5 轮询 轮询可以定义为一种方法,无论传输中存在哪些数据,它都执行周期性请求。定期请求以同步方式发送。客户端在指定的时间间隔内向服务器发出定期请求。服务器的响应包括可用数据或其中的一些警告消息。 长轮询 顾名思义,长轮询包括类
示例: bidirectional 在正常情况下, 客户端发送请求,服务器返回结果,这样一问一答的方式就是request-response rpc 模型。 但是对于一些用户, 比如 IoT 的开发者, 可能需要在某些时候发送通知给客户端。 如果客户端和服务端都配两套代码就显得多余和臃肿了。 rpcx实现了一个简单的通知机制。 首先你需要缓存客户端的连接,可能还需要将用户的ID和连接进行关联, 以便
本文向大家介绍HTML5中浏览上下文之间的双向通信,包括了HTML5中浏览上下文之间的双向通信的使用技巧和注意事项,需要的朋友参考一下 浏览上下文之间的双向通信称为通道消息传递。对于跨多个来源的通信很有用。 创建messageChannel时,它在内部创建两个端口来发送数据并转发到另一个浏览上下文。 postMessage() -发布消息抛出通道 start() -发送数据 close() -关闭