Android,RPC原理,C语言实现Binder跨进程通信Demo

RPC原理图

在这里插入图片描述

Binder C语言层的Demo演示

新建目录

在这里插入图片描述

把两个文件拷贝到我们的Demo下面

在这里插入图片描述

1.binder_server.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include <stdbool.h>
#include <string.h>
#include "binder.h"#define LOG_TAG "BinderServer"
#include <log/log.h>#define HELLO_BINDER     1
#define HELLO_BINDER_TO  2//服务就是被调用的函数
void hellobinder(void)
{static int cnt = 0;ALOGW("hello : %d\n", ++cnt);
}int hellobinder_to(char *name)
{static int cnt = 0;ALOGW("hello to %s : %d\n", name, ++cnt);return cnt;
}//回调函数
int hellobinder_service_handler(struct binder_state *bs,struct binder_transaction_data_secctx *txn_secctx,struct binder_io *msg,struct binder_io *reply)
{struct binder_transaction_data *txn = &txn_secctx->transaction_data;/* 根据txn->code知道要调用哪一个函数* 参数, 从msg取出* 返回结果, 把结果放入reply*//* sayhello* sayhello_to*/uint16_t *s;char name[512];size_t len;//uint32_t handle;uint32_t strict_policy;int i;// Equivalent to Parcel::enforceInterface(), reading the RPC// header with the strict mode policy mask and the interface name.// Note that we ignore the strict_policy and don't propagate it// further (since we do no outbound RPCs anyway).strict_policy = bio_get_uint32(msg);//code 用于判断我们需要调用哪一个函数,客户端远程调用哪个服务端函数switch(txn->code) { case HELLO_BINDER:hellobinder();//给reply写一个值为0bio_put_uint32(reply, 0); /* no exception */return 0;case HELLO_BINDER_TO:/* 从msg里取出字符串 */s = bio_get_string16(msg, &len);  //"IHelloService"s = bio_get_string16(msg, &len);  // nameif (s == NULL) {return -1;}for (i = 0; i < len; i++)name[i] = s[i];name[i] = '\0';/* 处理 */i = hellobinder_to(name);/* 把结果放入reply 给回客户端*/bio_put_uint32(reply, 0); /* no exception */bio_put_uint32(reply, i);break;default:fprintf(stderr, "unknown code %d\n", txn->code);return -1;}return 0;
}// 进程的 Binder 回调函数
//binder_transaction_data_secctx主要的数据,msg客户端传递过来的函数的参数,reply返回给客户端的数据
int test_server_handler(struct binder_state *bs,struct binder_transaction_data_secctx *txn_secctx,struct binder_io *msg,struct binder_io *reply)
{//取出数据,struct binder_transaction_data *txn = &txn_secctx->transaction_data;//函数指针,int (*handler)(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply);// txn->target.ptr 是 svcmgr_publish 传入的第二个参数handler = (int (*)(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply))txn->target.ptr;//调用函数指针,那么就会调用txn->target.ptr;这个指针,那么就是hellobinder_service_handlerreturn handler(bs, txn, msg, ,reply);
}int main(int argc, char **argv)
{struct binder_state *bs;//值为 0uint32_t svcmgr = BINDER_SERVICE_MANAGER;uint32_t handle;int ret;//初始化驱动bs = binder_open("/dev/binder", 128*1024);if (!bs) {fprintf(stderr, "failed to open binder driver\n");return -1;}//添加服务hellobinder_service_handler 是 hello 服务对应的回调函数//bs打开启动返回的一个int值,句柄,svcmgr表示把数据发到这个进程中,是ServiceManager,hello是注册的服务的名字//当我们注册的时候把这个hellobinder_service_handler指针传给驱动,驱动就记住hello服务回调是它,客户端需要调用hello服务的时候ret = svcmgr_publish(bs, svcmgr, "hello", hellobinder_service_handler);if (ret) {fprintf(stderr, "failed to publish hello service\n");return -1;}//test_server_handler  进程的 Binder 回调函数,进入循环服务端就不会挂掉,一直执行//binder收到数据,就解析,解析好就传给test_server_handlerbinder_loop(bs, test_server_handler);return 0;
}

在这里插入图片描述

binder_transaction_data_secctx

在这里插入图片描述

主要的数据结构是在这里

在这里插入图片描述

2.binder_client.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include <stdbool.h>
#include <string.h>
#include "binder.h"#define HELLO_BINDER     1
#define HELLO_BINDER_TO  2int g_handle = 0;
struct binder_state *g_bs;void sayhello(void)
{unsigned iodata[512/4];struct binder_io msg, reply;/* 构造binder_io *///初始化msg数据,表示的是所调用的服务端函数所需的参数bio_init(&msg, iodata, sizeof(iodata), 4);/* 放入参数 *///把数据写入msg中bio_put_uint32(&msg, 0);  // strict mode headerbio_put_string16_x(&msg, "IHelloService");/* 调用binder_call *///发起远程调用,g_bs是binder_open返回的一个句柄,msg函数的参数,reply服务端返回值,g_handle是hello服务在客户端的一个句柄索引,通过它才能找到对应的服务端,HELLO_BINDER是code,表示要调用服务端的哪个函数if (binder_call(g_bs, &msg, &reply, g_handle, HELLO_BINDER))return ;/* 从reply中解析出返回值 *///解析服务端返回的数据binder_done(g_bs, &msg, &reply);}int main(int argc, char **argv)
{int fd;struct binder_state *bs;uint32_t svcmgr = BINDER_SERVICE_MANAGER;int ret;bs = binder_open("/dev/binder", 128*1024);if (!bs) {fprintf(stderr, "failed to open binder driver\n");return -1;}g_bs = bs;/* get service 查找服务,bs是binder_open的返回值,svcmgr是servicemanager表示数据要发送给它,hello是查找服务的名字*///g_handle句柄,索引g_handle = svcmgr_lookup(bs, svcmgr, "hello");if (!g_handle) {return -1;} //调用服务,发起远程调用sayhello();}

编写bp文件

cc_defaults {name: "bindertestflags",cflags: ["-Wall","-Wextra","-Werror","-Wno-unused-parameter","-Wno-missing-field-initializers","-Wno-unused-parameter","-Wno-unused-variable","-Wno-incompatible-pointer-types","-Wno-sign-compare",],product_variables: {binder32bit: {cflags: ["-DBINDER_IPC_32BIT=1"],},},shared_libs: ["liblog"],
}
//c的可执行程序
cc_binary {name: "binderclient",defaults: ["bindertestflags"],vendor: true, srcs: ["binder_client.c","binder.c",],
}cc_binary {name: "binderserver",defaults: ["bindertestflags"],vendor: true, srcs: ["binder_server.c","binder.c",],
}// cc_binary {
//     name: "myservicemanager",
//     defaults: ["mybindertest_flags"],
//     srcs: [
//         "service_manager.c",
//         "binder.c",
//     ],
//     shared_libs: ["libcutils", "libselinux"],
// }

把编译出来的两个二进制文件push到设备中测试

在这里插入图片描述

看到hello已经被调用了说明跨进程通信成功了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357867.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET C# 操作Neo4j图数据库

.NET C# 操作Neo4j图数据库 目录 .NET C# 操作Neo4j图数据库环境Code 环境 VisualStudio2022 .NET 6 Neo4j.Driver 5.21 Code // 连接设置 var uri "bolt://localhost:7687"; var user "neo4j"; var password "password"; // 请替换为你的…

JavaScript 预编译与执行机制解析

在深入探讨JavaScript预编译与执行机制之前&#xff0c;我们首先需要明确几个基本概念&#xff1a;声明提升、函数执行上下文、全局执行上下文以及调用栈。这些概念共同构成了JavaScript运行时环境的核心组成部分&#xff0c;对于理解代码的执行流程至关重要。本文将围绕这些核…

SpringBoot配置第三方专业缓存技术jetcache远程缓存方案和本地缓存方案

JetCache 是一个基于 Java 的分布式缓存解决方案&#xff0c;旨在提供高性能和可扩展性。它支持多种后端存储&#xff0c;如 Redis、Hazelcast、Tair 等&#xff0c;可以作为应用程序的缓存层&#xff0c;有效地提升数据访问性能和响应速度。 JetCache 的主要特点包括&#x…

②-Ⅱ单细胞学习-组间及样本细胞比例分析(补充)

数据加载 ①单细胞学习-数据读取、降维和分群_subset函数单细胞群-CSDN博客‘ #2024年6月20日 单细胞组间差异分析升级# rm(list ls()) library(Seurat)#数据加载&#xff08;在第一步已经处理好的数据&#xff09; load("scedata1.RData")#这里是经过质控和降维…

MongoDB数据库的安装和删除

MongoDB数据库的删除和安装 1、删除MongoDB数据库2、下载MongoDB数据库1)、自定义安装2)、注意可视化可以取消勾选 1、删除MongoDB数据库 没有下载过的&#xff0c;可以直接跳到下面的安装过程↓ 我们电脑中如果有下载过MongoDB数据库&#xff0c;要更换版本的话&#xff0c;其…

能正常执行但是 cion 标红/没有字段提示

ctrl q 退出 clion 找到工程根目录&#xff0c;删除隐藏文件 .idea 再重新打开 clion 标红消失&#xff0c;同时再次输入函数/类属性&#xff0c;出现字段提示 clion 的智能提示方案存储在 .idea 文件中&#xff0c;如果工程能够正常编译执行&#xff0c;那么说明是智能提示…

基于STM32的智能家居安防系统

目录 引言环境准备智能家居安防系统基础代码实现&#xff1a;实现智能家居安防系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;智能家居安防管理与优化问题解决方案与优化收尾与总结 1. 引言 智能家居安防系统通过使…

第T2周:彩色图片分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 &#x1f449; 要求&#xff1a; 学习如何编写一个完整的深度学习程序了解分类彩色图片会灰度图片有什么区别测试集accuracy到达72% &#x1f9be;我的环境&am…

前端下载文件流,axios设置responseType: arraybuffer/blob无效

项目中调用后端下载文件接口&#xff0c;设置responseType: arraybuffer,实际拿到的数据data是字符串 axios({method: post,url: /api/v1/records/recording-file/play,// 如果有需要发送的数据&#xff0c;可以放在这里data: { uuid: 06e7075d-4ce0-476f-88cb-87fb0a1b4844 }…

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox&#xff1b; 2.下载并安装Vagrant; 3.打开cmd窗口&#xff0c;执行命令vagrant init centos/7&#xff0c;初始化centos环境&#xff0c;该步骤受网络带宽影响&#xff0c;可能挂级30分钟到1个小时&#xff1b; 4.启动虚拟机&#xff1a;vagrant up&…

基于CDMA的多用户水下无线光通信(2)——系统模型和基于子空间的延时估计

本文首先介绍了基于CDMA的多用户UOWC系统模型&#xff0c;并给出了多用户收发信号的数学模型。然后介绍基于子空间的延时估计算法&#xff0c;该算法只需要已知所有用户的扩频码&#xff0c;然后根据扩频波形的循环移位在观测空间的信号子空间上的投影进行延时估计。 1、基于C…

【Linux进程】进程的 切换 与 调度(图形化解析,小白一看就懂!!!)

目录 &#x1f525;前言&#x1f525; &#x1f4a7;进程切换&#x1f4a7; &#x1f4a7;进程调度&#x1f4a7; &#x1f525;总结与提炼&#x1f525; &#x1f525;共勉&#x1f525; &#x1f525;前言&#x1f525; 在 Linux 操作系统中&#xff0c;进程的 调度 与 …

【STM32-新建工程-寄存器版本】

STM32-新建工程-寄存器版本 ■ 下载相关STM32Cube官方固件包&#xff08;F1&#xff0c;F4&#xff0c;F7&#xff0c;H7&#xff09;■ 1. ST官方搜索STM32Cube■ 2. 搜索 STM32Cube■ 3. 点击获取软件■ 4. 选择对应的版本下载■ 5. 输入账号信息■ 6. 出现下载弹框&#xff…

React@16.x(34)动画(中)

目录 3&#xff0c;SwitchTransition3.1&#xff0c;原理3.1.2&#xff0c;key3.1.2&#xff0c;mode 3.2&#xff0c;举例3.3&#xff0c;结合 animate.css 4&#xff0c;TransitionGroup4.1&#xff0c;其他属性4.1.2&#xff0c;appear4.1.2&#xff0c;component4.1.3&…

MFC学习--CListCtrl复选框以及选择

如何展示复选框 //LVS_EX_CHECKBOXES每一行的最前面带个复选框//LVS_EX_FULLROWSELECT整行选中//LVS_EX_GRIDLINES网格线//LVS_EX_HEADERDRAGDROP列表头可以拖动m_listctl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES); 全选&#xff0c;全…

如何获得一个Oracle 23ai数据库(vagrant box)

准确的说&#xff0c;是Oracle 23ai Free Developer版&#xff0c;因为企业版目前只在云上&#xff08;OCI和Azure&#xff09;和ECC上提供。 前面我博客介绍了3种方法&#xff1a; Virtual ApplianceRPM安装Docker 今天介绍最近新出的一种方法&#xff0c;也是我最为推荐的…

探索CSS clip-path: polygon():塑造元素的无限可能

在CSS的世界里&#xff0c;clip-path 属性赋予了开发者前所未有的能力&#xff0c;让他们能够以非传统的方式裁剪页面元素&#xff0c;创造出独特的视觉效果。其中&#xff0c;polygon() 函数尤其强大&#xff0c;它允许你使用多边形来定义裁剪区域的形状&#xff0c;从而实现各…

定时器-前端使用定时器3s轮询状态接口,2min为接口超时

背景 众所周知&#xff0c;后端是处理不了复杂的任务的&#xff0c;所以经过人家的技术讨论之后&#xff0c;把业务放在前端来实现。记录一下这次的离大谱需求吧。 如图所示&#xff0c;这个页面有5个列表&#xff0c;默认加载计划列表。但是由于后端的种种原因&#xff0c;这…

【C#】使用数字和时间方法ToString()格式化输出字符串显示

在C#编程项目开发中&#xff0c;几乎所有对象都有格式化字符串方法&#xff0c;其中常见的是数字和时间的格式化输出多少不一样&#xff0c;按实际需要而定吧&#xff0c;现记录如下&#xff0c;以后会用得上。 文章目录 数字格式化时间格式化 数字格式化 例如&#xff0c;保留…

WPF三方UI库全局应用MessageBox样式(.NET6版本)

一、问题场景 使用HandyControl简写HC 作为基础UI组件库时&#xff0c;希望系统中所有的MessageBox 样式都使用HC的MessageBox&#xff0c;常规操作如下&#xff1a; 在对应的xxxx.cs 顶部使用using 指定特定类的命名空间。 using MessageBox HandyControl.Controls.Message…