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

news2025/1/12 9:04:58

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写一个值为0
		bio_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);  // name
		if (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_handler
	return handler(bs, txn, msg, ,reply);
}


int main(int argc, char **argv)
{
    struct binder_state *bs;
    //值为 0
    uint32_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_handler
    binder_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  2


int 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 header
    bio_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.coloradmin.cn/o/1854357.html

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

相关文章

【FreeRTOS】任务管理与调度

文章目录 调度&#xff1a;总结 调度&#xff1a; 相同优先级的任务轮流运行最高优先级的任务先运行 可以得出结论如下&#xff1a; a 高优先级的任务在运行&#xff0c;未执行完&#xff0c;更低优先级的任务无法运行b 一旦高优先级任务就绪&#xff0c;它会马上运行&#xf…

AI大模型企业应用实战(14)-langchain的Embedding

1 安装依赖 ! pip install --upgrade langchain ! pip install --upgrade openai0.27.8 ! pip install -U langchain-openai ! pip show openai ! pip show langchain ! pip show langchain-openai 2 Embed_documents # 1. 导入所需的库 from langchain_openai import Open…

阿里云服务器618没想到这么便宜,买早了!

2年前&#xff0c;我买了个服务器&#xff0c;租用服务器&#xff08;ECS5&#xff09;和网络宽带&#xff08;1M&#xff09;&#xff0c;可以说是非常非常低的配置了。 当时5年的折扣力度最大&#xff0c;但是打完折后&#xff0c;价格依然要近3000多元。 最近看到阿里云618活…

C++风流和MATLAB | Python | CUDA 库埃特流泊肃叶流薄膜流体

&#x1f3af;要点 &#x1f3af;无滑移速度边界条件&#xff1a;&#x1f58a;反弹法计算库埃特流、泊肃叶流 | &#x1f58a;湿节点法计算库埃特流、泊肃叶流 | &#x1f3af;力模型&#xff1a;&#x1f58a;反弹法和不同的格子玻尔兹曼体力模型计算泊肃叶流 | &#x1f58…

winmail添加gmail和QQ邮箱(现已更新为outlook mail)

想在windows自带的邮件桌面应用里&#xff0c;不仅能访问outlook邮件&#xff0c;也能访问gmail邮件和QQ邮件的方法。 参考文章&#xff1a; Windows 10 的邮件怎么添加并同步 Gmail&#xff1f;​www.zhihu.com/question/53079836/answer/147669935?utm_psn178781450843941…

预训练是什么?

预训练是什么&#xff1f; 图像领域的预训练 在介绍图像领域的预训练之前&#xff0c;我们首先介绍下卷积神经网络&#xff08;CNN&#xff09;&#xff0c;CNN 一般用于图片分类任务&#xff0c;并且CNN 由多个层级结构组成&#xff0c;不同层学到的图像特征也不同&#xff…

【LLM之KG】CoK论文阅读笔记

研究背景 大规模语言模型&#xff08;LLMs&#xff09;在许多自然语言处理&#xff08;NLP&#xff09;任务中取得了显著进展&#xff0c;特别是在零样本/少样本学习&#xff08;In-Context Learning, ICL&#xff09;方面。ICL不需要更新模型参数&#xff0c;只需利用几个标注…

谁说串口通信波特率越高越好?

在电子世界里&#xff0c;串口通信就像是电子设备之间的“悄悄话”&#xff0c;它们通过串行数据传输来交换信息。但你知道吗&#xff1f;串口通信的波特率并不是越高越好&#xff0c;这事儿得好好聊聊。 1.什么是串口通信&#xff1f; 串口通信&#xff0c;就像它的名字一样&a…

【转型指南】从软件测试到技术多面手

★ 导言 小艺是一位毕业于985的计算机硕士&#xff0c;工作多年&#xff0c;现在某大厂从事软件测试方面的管理工作。目前在工作中游刃有余&#xff0c;但面对技术的飞速变化和职业发展的不确定性&#xff0c;还是难免焦虑&#xff0c;正在积极思考如何进一步提升自己&#xff…

谈谈面试常考题:懒加载,防抖,节流(方法实现详解)

前言 最近在学习中确实收获了挺多东西&#xff0c;其中我觉得有必要拿来进行分享一下的就是懒加载了&#xff0c;还有相关的防抖和节流。因为在浏览器中这些都是属于很常见的性能优化&#xff0c;面试也是常考题。话不多说&#xff0c;速度发车。 什么是懒加载&#xff1f;懒…

关于Pytorch转换为MindSpore的一点建议

一、事先准备 必须要对Mindspore有一些了解&#xff0c;因为这个框架确实有些和其它流程不一样的地方&#xff0c;比如算子计算、训练过程中的自动微分&#xff0c;所以这两个课程要好好过一遍&#xff0c;官网介绍文档最好也要过一遍 1、零基础Mindspore&#xff1a;https://…

pytest测试框架flaky插件重试失败用例

Pytest提供了丰富的插件来扩展其功能&#xff0c;本章介绍下插件flaky &#xff0c;用于在测试用例失败时自动重新运行这些测试用例。与前面文章介绍的插件pytest-rerunfailures功能有些类似&#xff0c;但是功能上不如pytest-rerunfailures插件丰富。 flaky官方并没有明确pyt…

微软搁置水下数据中心项目——项目纳蒂克相比陆地服务器故障更少

“我的团队努力了&#xff0c;并且成功了&#xff0c;”COI负责人诺埃尔沃尔什说。 微软已悄然终止了始于2013年的水下数据中心&#xff08;UDC&#xff09;项目“纳蒂克”。该公司向DatacenterDynamics确认了这一消息&#xff0c;微软云运营与创新部门负责人诺埃尔沃尔什表示…

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

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

vuex的深入学习[基于vuex3]----篇(二)

store对象的创建 store的传递图 创建语句索引 创建vuex的语句为new Vuex.Store({…})Vuex的入口文件是index.js,store是index.js导出的store类store类是store.js文件中定义的。 Store的构造函数constructor 判断vuex是否被注入&#xff0c;就是将vue挂载在window对象上&am…

[技术笔记] 元器件采购之Flash的国内、外厂商Top5

国外Top5 1、Micron&#xff08;镁光&#xff09;半导体 2、Toshiba&#xff08;东芝&#xff09; 3、Hynix&#xff08;海力士&#xff09; 4、Samsung&#xff08;三星&#xff09; 5、Intel&#xff08;因特尔&#xff09; 6、SanDisk&#xff08;闪迪&#xff09; 7…

瑞_MongoDB_MongoDB副本集

文章目录 1 MongoDB副本集-Replica Sets1.1 简介1.2 副本集的三个角色1.3 副本集架构目标1.4 副本集的创建1.4.1 创建主节点1.4.2 创建副本节点1.4.3 创建仲裁节点1.4.4 初始化配置副本集和主节点1.4.5 查看副本集的配置内容 rs.conf()1.4.6 查看副本集状态1.4.7 添加副本从节点…

1.4 Kettle 数据同步工具详细教程

工具介绍 一、概述 Kettle&#xff0c;又名 Pentaho Data Integration&#xff08;PDI&#xff09;&#xff0c;是一个开源的数据集成工具&#xff0c;最初由 Pentaho 公司开发。它能够从多种数据源提取、转换并加载&#xff08;ETL&#xff09;数据&#xff0c;适用于数据仓…

2023-2024 学年第二学期小学数学六年级期末质量检测模拟(制作:王胤皓)(90分钟)

word效果预览&#xff1a; 一、我会填 1. 1.\hspace{0.5em} 1. 一个多位数&#xff0c;亿位上是次小的素数&#xff0c;千位上是最小的质数的立方&#xff0c;十万位是 10 10 10 和 15 15 15 的最大公约数&#xff0c;万位是最小的合数&#xff0c;十位上的数既不是质数也…