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.mzph.cn/diannao/32920.shtml

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

相关文章

多路h265监控录放开发-(12)完成全部开始录制和全部停止录制代码

xviewer.h 新增 public: void StartRecord();//126 开始全部摄像头录制 void StopRecord();//126 停止全部摄像头录制 xviewer.cpp 新增 //视频录制 static vector<XCameraRecord*> records;//126void XViewer::StartRecord() //开始全部摄像头录制 126 {StopRecord…

基于JSP的“塞纳河畔左岸”的咖啡馆管理系统

开头语&#xff1a; 塞纳河畔左岸的咖啡&#xff0c;我手一杯品尝的你美~ 哎哟&#xff0c;不错哦&#xff01;我们今天来介绍一下咖啡馆管理系统&#xff01; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果你对咖啡馆管理系统感兴趣或有相关需求&#xff0c;欢迎联…

AGV机器人的调度开发分析(1)- 内核中的路线规划

准备开始写一个系列&#xff0c;介绍下AGV机器人的调度的开发和应用。 按照openTCS的核心内容&#xff0c;国内多家广泛应用于AGV的调度。那么架构图如下&#xff1a; Kernel中有一个是Routing&#xff0c;这是路由规划模块&#xff0c;需要实现的细节功能包括如下&#xff1a…

Django 模版转义

1&#xff0c;模版转义的作用 Django模版系统默认会自动转义所有变量。这意味着&#xff0c;如果你在模版中输出一个变量&#xff0c;它的内容会被转义&#xff0c;以防止跨站脚本攻击&#xff08;XSS&#xff09;。例如&#xff0c;如果你的变量包含HTML标签&#xff0c;这些…

长亭谛听教程部署和详细教程

PPT 图片先挂着 挺概念的 谛听的能力 hw的时候可能会问你用过的安全产品能力能加分挺重要 溯源反制 反制很重要感觉很厉害 取证分析 诱捕牵制 其实就是蜜罐 有模板直接爬取某些网页模板进行伪装 部署要求 挺低的 对linux内核版本有要求 需要root 还有系统配置也要修改 …

网络编程篇:HTTP协议

一.预备知识 在客户端访问服务端时&#xff0c;要用ipport&#xff0c;但是在日常用户访问服务端的时候&#xff0c;并不会直接使用ip&#xff0c;而是使用域名&#xff0c;比如&#xff1a;百度(www.baidu,com)。 …

智能优化算法改进策略之局部搜索算子(八)--Powell方法

1、原理介绍 Powell方法[1]是一种无约束优化算法&#xff0c;又称为方向加速法&#xff0c;用于寻找多变量函数的极小值。其基本思想是在迭代中逐次产生Q共轭方向组&#xff0c;本质上它属于不需计算导数的共轭方向法。每次迭代后&#xff0c;算法会更新搜索方向&#xff0c;并…

Java内存泄漏检测和分析介绍

在Java中&#xff0c;内存泄漏检测和分析是一个重要的任务&#xff0c;可以通过以下几种方式进行&#xff1a; 1. 使用VisualVM VisualVM是一个可视化工具&#xff0c;可以监控、分析Java应用程序的内存消耗。它可以显示堆内存、垃圾收集、线程等信息&#xff0c;并且可以对内…

英伟达下一代DLSS或利用人工智能

英伟达的黄仁勋在2024年Computex展会上的问答环节中&#xff0c;提前透露了公司未来几代深度学习超采样&#xff08;DLSS&#xff09;技术的发展方向。在回答有关DLSS的问题时&#xff0c;黄仁勋表示&#xff0c;未来我们将看到通过纯粹的人工智能生成的纹理和对象。他还提到&a…

构建下一代数据解决方案:SingleStore、MinIO 和现代 Datalake 堆栈

SingleStore 是专为数据密集型工作负载而设计的云原生数据库。它是一个分布式关系 SQL 数据库管理系统&#xff0c;支持 ANSI SQL&#xff0c;并因其在数据引入、事务处理和查询处理方面的速度而受到认可。SingleStore 可以存储关系、JSON、图形和时间序列数据&#xff0c;以满…

AI 大模型企业应用实战(13)-Lostinthemiddle长上下文精度处理

1 长文本切分信息丢失处理方案 10检索时性能大幅下降相关信息在头尾性能最高检索 ->> 排序 ->使用 实战 安装依赖&#xff1a; ! pip install sentence-transformers 演示如何使用 Langchain 库中的组件来处理长文本和检索相关信息。 导入所需的库使用指定的预训…

(4) cmake编译静态库和动态库

文章目录 静态库整体代码动态库编译整体代码执行结果(静态) 静态库整体代码 static.h #pragma onecevoid static_demo();static.cpp #include "static.h" #include <iostream>void static_demo(){std::cout<<"static demo"<<std::end…

Posix多线程编程总结

Posix在线文档&#xff1a; The Single UNIX Specification, Version 2 (opengroup.org) 本文主要参考这位大神的文章&#xff1a; Posix多线程编程学习笔记 - 凌峰布衣 - 博客园 (cnblogs.com) 线程安全问题 多线程编程中&#xff0c;经常遇到的就是线程安全问题&#xff0c;或…

PINN解偏微分方程实例4

PINN解偏微分方程实例4 一、正问题1. Diffusion equation2. Burgers’ equation3. Allen–Cahn equation4. Wave equation 二、反问题1. Burgers’ equation3. 部分代码示例 本文使用 PINN解偏微分方程实例1中展示的代码求解了以四个具体的偏微分方程&#xff0c;包括Diffusio…

第T2周:彩色图片分类

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

测试测量-DMM直流精度

测试测量-DMM直流精度 最近去面试&#xff0c;发现了自己许多不足&#xff0c;比如我从未考虑过万用表准或者不准&#xff0c;或者万用表有多准&#xff1f; 在过去的实验室中&#xff0c;常用的DMM有KEYSIGHT 34401A以及 KEITHLEY THD2015&#xff0c;就以这两台为例&#x…

线程C++

#include <thread> #include <chrono> #include <cmath> #include <mutex> #include <iostream> using namespace std;mutex mtx; void threadCommunicat() {int ans 0;while (ans<3){mtx.lock();//上锁cout << "ans" <…

预制直埋聚氨酯保温管

&#x1f600;宝子们&#xff0c;今天来给大家介绍一下预制聚氨酯直埋保温管&#x1f389;&#xff01; 它可是个好东西&#x1f44d;&#xff0c;具有超强的保温性能&#x1f9ca;&#xff0c;能够有效保持管道内的温度&#x1f60e;。 而且它还很耐用&#x1f4aa;&#xff0…

用 idea 启动多个实例

在学习负载均衡的时候&#xff0c;要模拟多个实例均提供一个服务&#xff0c;我们要如何用 idea 启动多个实例呢&#xff1f; 如下图&#xff0c;我们已经启动了一个 ProductService 服务&#xff0c;现在想再启动两个相同的服务 1. 选中要启动的服务,右键选择 Copy Configura…

用Java获取键盘输入数的个十百位数

这段Java代码是一个简单的程序&#xff0c;用于接收用户输入的一个三位数&#xff0c;并将其分解为个位、十位和百位数字&#xff0c;然后分别打印出来。下面是代码的详细解释&#xff1a; 导入所需类库: import java.util.Scanner;&#xff1a;导入Scanner类&#xff0c;用于从…