Android : 跟我学Binder --- (3) C程序示例
目录:
Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?
Android : 跟我学Binder --- (2) AIDL分析及手动实现
Android : 跟我学Binder --- (3) C程序示例
Android : 跟我学Binder --- (4) 驱动情景分析
Android : 跟我学Binder --- (5) C++实现
Android : 跟我学Binder --- (6) JAVA实现
一、Binder框架分析
1、IPC、LPC和RPC的概念:
IPC: (Inter Process Communication )跨进程通信,泛指进程之间任何形式的通信行为,它不仅包括各种形式的消息传递,还可以指共享资源,以及同步对象;
LPC: (Local Procedure Call )本地过程调用,用在多任务操作系统中,使得同时运行的任务能互相会话。这些任务共享内存空间使任务同步和互相发送信息;(IPC的封装)
RPC:(Reomote Procedure Call )远程过程调用,类似于LPC,只是在网上工作。RPC开始是出现在Sun微系统公司和HP公司的运行UNIX操作系统的计算机中;
2、通信架构:
Client/Server <---> service manager 交互流程:
server ---------addservice-------> service manager
client ---------getservice--------> service manager

注:ServiceManager首先向binder驱动注册为服务管理者,handle为0;
3、简析示例代码(非完整流程):
①android_5.0.2_32\frameworks\native\cmds\servicemanager\service_manager.c //管理server注册的服务(进程)
a. binder_open //打开驱动
b. binder_become_context_manager //告诉驱动注册为service manager
c. binder_loop(bs, svcmgr_handler);
c. res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //读数据
c. binder_parse // 解析数据 /*处理数据 : svcmgr_handler*/
SVC_MGR_GET_SERVICE/SVC_MGR_CHECK_SERVICE : 获取服务
SVC_MGR_ADD_SERVICE : 注册服务
/*有必要则回复数据*/
.......
②android_5.0.2_32\frameworks\native\cmds\servicemanager\bctest.c //client测试代码
注册服务的过程:
a. binder_open //打开驱动
b. svcmgr_publish //构造数据
c. binder_call(bs, &msg, &reply, , SVC_MGR_ADD_SERVICE)
// 含有服务的名字
// 它会含有servicemanager回复的数据
// 0表示servicemanager
// code: 表示要调用servicemanager中的"addservice函数" 获取服务的过程:
a. binder_open //打开驱动
b. svcmgr_lookup //构造数据
c. binder_call(bs, &msg, &reply, , SVC_MGR_CHECK_SERVICE)
// 含有服务的名字
// 它会含有servicemanager回复的数据, 表示提供服务的进程
// 0表示servicemanager
// code: 表示要调用servicemanager中的"getservice函数
③android_5.0.2_32\frameworks\native\cmds\servicemanager\binder.c //封装好的C函数
(1)构造参数:放在一个buffer用binder_io来描述;
unsigned iodata[/]; //用binder_io来管理这个缓冲区
struct binder_io msg, reply;
...
bio_init(&msg, iodata, sizeof(iodata), ); //初始化binder_io对象 /*可以放入各类型参数,反之通过get方法获取*/
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, SVC_MGR_NAME);
bio_put_string16_x(&msg, name);
bio_put_obj(&msg, ptr);
... /*调用binder_call(struct binder_state *bs,
struct binder_io *msg/*提供参数*/,
struct binder_io *reply/*获得回复*/,
uint32_t target/*发送对象*/,
uint32_t code/*调用函数*/)*/ if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
return -;
(2)根据 binder_io、target、code 构造writebuf:
struct binder_write_read bwr;
struct {
uint32_t cmd;
struct binder_transaction_data txn;
} __attribute__((packed)) writebuf;
unsigned readbuf[];
.... writebuf.cmd = BC_TRANSACTION;
writebuf.txn.target.handle = target;
writebuf.txn.code = code;
writebuf.txn.flags = ;
writebuf.txn.data_size = msg->data - msg->data0;
writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; bwr.write_size = sizeof(writebuf);
bwr.write_consumed = ;
bwr.write_buffer = (uintptr_t) &writebuf;
其中binder_write_read 结构体在内核代码中的定义:
struct binder_write_read {
signed long write_size; /* bytes to write */
signed long write_consumed; /* bytes consumed by driver */
unsigned long write_buffer;
signed long read_size; /* bytes to read */
signed long read_consumed; /* bytes consumed by driver */
unsigned long read_buffer;
};
其中binder_transaction_data结构体在内核代码中的定义:
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
size_t handle; /* target descriptor of command transaction */
void *ptr; /* target descriptor of return transaction */
} target;
void *cookie; /* target object cookie */
unsigned int code; /* transaction command */
/* General information about the transaction. */
unsigned int flags;
pid_t sender_pid;
uid_t sender_euid;
size_t data_size; /* number of bytes of data */
size_t offsets_size; /* number of bytes of offsets */
/* If this transaction is inline, the data immediately
* follows here; otherwise, it ends with a pointer to
* the data buffer.
*/
union {
struct {
/* transaction data */
const void *buffer;
/* offsets from buffer to flat_binder_object structs */
const void *offsets;
} ptr;
uint8_t buf[];
} data;
};
(3)通过ioctl发送数据:
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = ;
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < ) {
fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
goto fail;
}
res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, ); //解析返回的数据
if (res == ) return ;
if (res < ) goto fail;
}
框架流程总结:
client端: binder_open ---> 获得服务handle ---> 构造参数binder_io ---> 调用binder_call ---> 解析返回的binder_io;
server端:binder_open ---> 注册服务 ---> ioctl读取数据(binder_write_read )---> 解析数据(binder_transaction_data ) ---> 获得binder_io并根据code调用对应函数 ---> 把返回值发送给client;

二、编写程序
1.参考service_manager.c编写test_server.c添加服务:
/* Copyright 2008 The Android Open Source Project
*/ #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include<stdbool.h>
#include <string.h> #include <private/android_filesystem_config.h> #include "binder.h"
#include "test_server.h" int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
{
int status;
unsigned iodata[/];
struct binder_io msg, reply; bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, SVC_MGR_NAME);
bio_put_string16_x(&msg, name);
bio_put_obj(&msg, ptr); if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
return -; status = bio_get_uint32(&reply); binder_done(bs, &msg, &reply); return status;
} void sayhello(void)
{
static int cnt = ;
fprintf(stderr, "say hello : %d\n", ++cnt);
} int sayhello_to(char *name)
{
static int cnt = ;
fprintf(stderr, "say hello to %s : %d\n", name, ++cnt);
return cnt;
} void saygoodbye(void)
{
static int cnt = ;
fprintf(stderr, "say goodbye : %d\n", ++cnt);
} int saygoodbye_to(char *name)
{
static int cnt = ;
fprintf(stderr, "say goodbye to %s : %d\n", name, ++cnt);
return cnt;
} int hello_service_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
/* 根据txn->code知道要调用哪一个函数
* 如果需要参数, 可以从msg取出
* 如果要返回结果, 可以把结果放入reply
*/ /* sayhello
* sayhello_to
*/ uint16_t *s;
char name[];
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); // 取出0,后面才是传过来的所需数据 switch(txn->code) {
case HELLO_SVR_CMD_SAYHELLO:
sayhello();
bio_put_uint32(reply, ); /* no exception */
return ; case HELLO_SVR_CMD_SAYHELLO_TO:
/* 从msg里取出字符串(16位转8位) */
s = bio_get_string16(msg, &len); //"IHelloService"
s = bio_get_string16(msg, &len); // name
if (s == NULL) {
return -;
}
for (i = ; i < len; i++)
name[i] = s[i];
name[i] = '\0'; /* 处理 */
i = sayhello_to(name); /* 把结果放入reply */
bio_put_uint32(reply, ); /* no exception */
bio_put_uint32(reply, i); break; default:
fprintf(stderr, "unknown code %d\n", txn->code);
return -;
} return ;
} int goodbye_service_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
/* 根据txn->code知道要调用哪一个函数
* 如果需要参数, 可以从msg取出
* 如果要返回结果, 可以把结果放入reply
*/ /* sayhello
* sayhello_to
*/ uint16_t *s;
char name[];
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); switch(txn->code) {
case GOODBYE_SVR_CMD_SAYGOODBYE:
saygoodbye();
bio_put_uint32(reply, ); /* no exception */
return ; case GOODBYE_SVR_CMD_SAYGOODBYE_TO:
/* 从msg里取出字符串(16位转8位) */
s = bio_get_string16(msg, &len); //"IGoodbyeService"
s = bio_get_string16(msg, &len); // name
if (s == NULL) {
return -;
}
for (i = ; i < len; i++)
name[i] = s[i];
name[i] = '\0'; /* 处理 */
i = saygoodbye_to(name); /* 把结果放入reply */
bio_put_uint32(reply, ); /* no exception */
bio_put_uint32(reply, i); break; default:
fprintf(stderr, "unknown code %d\n", txn->code);
return -;
} return ;
} int test_server_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
int (*handler)(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply); handler = (int (*)(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply))txn->target.ptr; return handler(bs, txn, msg, reply);
} int main(int argc, char **argv)
{
int fd;
struct binder_state *bs;
uint32_t svcmgr = BINDER_SERVICE_MANAGER;
uint32_t handle;
int ret; bs = binder_open(*);
if (!bs) {
fprintf(stderr, "failed to open binder driver\n");
return -;
} /* add service */
ret = svcmgr_publish(bs, svcmgr, "hello", hello_service_handler); //第三个参数值需要唯一,obj->binder = (uintptr_t)ptr;
if (ret) {
fprintf(stderr, "failed to publish hello service\n");
return -;
}
ret = svcmgr_publish(bs, svcmgr, "goodbye", goodbye_service_handler);
if (ret) {
fprintf(stderr, "failed to publish goodbye service\n");
} binder_set_maxthreads(bs, ); /* //binder_loop已封装如下步骤:
while (1)
{
/* read data */
/* parse data, and process */
/* reply */
}
*/
binder_loop(bs, test_server_handler); //通过函数test_server_handler处理消息 return ;
}
test_server.h :
#ifndef _TEST_SERVER_H
#define _TEST_SERVER_H #define HELLO_SVR_CMD_SAYHELLO 1
#define HELLO_SVR_CMD_SAYHELLO_TO 2 #define GOODBYE_SVR_CMD_SAYGOODBYE 1
#define GOODBYE_SVR_CMD_SAYGOODBYE_TO 2 #endif // _TEST_SERVER_H
2.编写test_client.c获得/使用服务:
/* Copyright 2008 The Android Open Source Project
*/ #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include<stdbool.h>
#include <string.h> #include <private/android_filesystem_config.h> #include "binder.h"
#include "test_server.h" uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
{
uint32_t handle;
unsigned iodata[/];
struct binder_io msg, reply; bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, SVC_MGR_NAME);
bio_put_string16_x(&msg, name); if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
return ; handle = bio_get_ref(&reply); if (handle)
binder_acquire(bs, handle); binder_done(bs, &msg, &reply); return handle;
} struct binder_state *g_bs;
uint32_t g_hello_handle;
uint32_t g_goodbye_handle; void sayhello(void)
{
unsigned iodata[/];
struct binder_io msg, reply; /* 构造binder_io */
bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header ,传入0
bio_put_string16_x(&msg, "IHelloService"); /* 放入参数 */ /* 调用binder_call */
if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO))
return ; /* 从reply中解析出返回值 */ binder_done(g_bs, &msg, &reply); } /*
*带参数
*/
int sayhello_to(char *name)
{
unsigned iodata[/];
struct binder_io msg, reply;
int ret;
int exception; /* 构造binder_io */
bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, "IHelloService"); /* 放入参数 */
bio_put_string16_x(&msg, name); /* 调用binder_call */
if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO_TO))
return ; /* 从reply中解析出返回值 */
exception = bio_get_uint32(&reply);
if (exception)
ret = -;
else
ret = bio_get_uint32(&reply); binder_done(g_bs, &msg, &reply); return ret; } void saygoodbye(void)
{
unsigned iodata[/];
struct binder_io msg, reply; /* 构造binder_io */
bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, "IGoodbyeService"); /* 放入参数 */ /* 调用binder_call */
if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE))
return ; /* 从reply中解析出返回值 */ binder_done(g_bs, &msg, &reply); } int saygoodbye_to(char *name)
{
unsigned iodata[/];
struct binder_io msg, reply;
int ret;
int exception; /* 构造binder_io */
bio_init(&msg, iodata, sizeof(iodata), );
bio_put_uint32(&msg, ); // strict mode header
bio_put_string16_x(&msg, "IGoodbyeService"); /* 放入参数 */
bio_put_string16_x(&msg, name); /* 调用binder_call */
if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE_TO))
return ; /* 从reply中解析出返回值 */
exception = bio_get_uint32(&reply);
if (exception)
ret = -;
else
ret = bio_get_uint32(&reply); binder_done(g_bs, &msg, &reply); return ret; } /* ./test_client hello
* ./test_client hello <name>
*/ int main(int argc, char **argv)
{
int fd;
struct binder_state *bs;
uint32_t svcmgr = BINDER_SERVICE_MANAGER;
uint32_t handle;
int ret; if (argc < ){
fprintf(stderr, "Usage:\n");
fprintf(stderr, "%s <hello|goodbye>\n", argv[]);
fprintf(stderr, "%s <hello|goodbye> <name>\n", argv[]);
return -;
} bs = binder_open(*);
if (!bs) {
fprintf(stderr, "failed to open binder driver\n");
return -;
}
g_bs = bs; /* get service */
handle = svcmgr_lookup(bs, svcmgr, "goodbye");
if (!handle) {
fprintf(stderr, "failed to get goodbye service\n");
return -;
}
g_goodbye_handle = handle;
fprintf(stderr, "Handle for goodbye service = %d\n", g_goodbye_handle); handle = svcmgr_lookup(bs, svcmgr, "hello");
if (!handle) {
fprintf(stderr, "failed to get hello service\n");
return -;
}
g_hello_handle = handle;
fprintf(stderr, "Handle for hello service = %d\n", g_hello_handle); /* send data to server */
if (!strcmp(argv[], "hello"))
{
if (argc == ) {
sayhello();
} else if (argc == ) {
ret = sayhello_to(argv[]);
fprintf(stderr, "get ret of sayhello_to = %d\n", ret);
}
} else if (!strcmp(argv[], "goodbye"))
{
if (argc == ) {
saygoodbye();
} else if (argc == ) {
ret = saygoodbye_to(argv[]);
fprintf(stderr, "get ret of sayhello_to = %d\n", ret);
}
} binder_release(bs, handle); return ;
}
3.编译脚本:
(1)Makefile
APPS = service_manager test_client test_server all : $(APPS) service_manager : service_manager.o binder.o
arm-linux-gcc -o $@ $^ -lpthread test_client : test_client.o binder.o
arm-linux-gcc -o $@ $^ -lpthread test_server : test_server.o binder.o
arm-linux-gcc -o $@ $^ -lpthread %.o : %.c
arm-linux-gcc -DBINDER_IPC_32BIT= -I include -c -o $@ $< clean:
rm $(APPS) -f; rm -f *.o
(2)Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS += -DBINDER_IPC_32BIT= LOCAL_SRC_FILES:= service_manager.c binder.c LOCAL_C_INCLUDES += system/core/include/cutils LOCAL_MODULE:= service_manager_my include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_CFLAGS += -DBINDER_IPC_32BIT= LOCAL_SRC_FILES:= test_server.c binder.c LOCAL_C_INCLUDES += system/core/include/cutils LOCAL_MODULE:= test_server include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_CFLAGS += -DBINDER_IPC_32BIT= LOCAL_SRC_FILES:= test_client.c binder.c LOCAL_C_INCLUDES += system/core/include/cutils LOCAL_MODULE:= test_client include $(BUILD_EXECUTABLE)
-end-
Android : 跟我学Binder --- (3) C程序示例的更多相关文章
- Android : 跟我学Binder --- (6) JAVA实现
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- Android : 跟我学Binder --- (5) C++实现
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- Android : 跟我学Binder --- (4) 驱动情景分析
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- Android : 跟我学Binder --- (2) AIDL分析及手动实现
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- 9.1 Binder系统_C程序示例_框架分析和编写程序
IPC : Inter-Process Communication, 进程间通信 A进程把数据原原本本的发给B,这就是IPC RPC : Remote Procedure Call, 远程过程调用 A ...
- 写给 Android 应用工程师的 Binder 原理剖析
写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...
- 深入理解Android IPC机制之Binder机制
Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...
- 【Android - IPC】之Binder机制简介
参考资料: 1.<Android开发艺术探索>第二章2.3.3 Binder 2.[Android Binder设计与实现-设计篇] 3.[Android Binder机制介绍] 1. 什 ...
随机推荐
- Go 初体验 - channel.2 - 超时机制
channel 虽然很好用,但是我们也要考虑异常情况,比如:超时 go 语言怎么解决这个超时问题呢? 可以利用 select 语句: select 的用法与 switch 语言非常类似,由 selec ...
- bootloader研究最后一关(中)
2011-03-12 17:04:13 今天的目的是要把bin文件烧录到nandflash中. 其实我有一个问题一直没弄明白.S3C2440自带的RAM和ROM是多大?看了规格书说它能控制1G的8个b ...
- perl 用网易发邮件报错 554 DT:SPM 163 smtp14
查看相关链接,貌似被当成垃圾邮件了,发不出去 554 DT:SPM 163 smtp14,EsCowACHUegmKpdc3giRMQ--.29617S2 1553410599,please see ...
- Node + Redis 实现分布式Session方案(转载)
Session是什么? Session 是面向连接的状态信息,是对 Http 无状态协议的补充. Session 怎么工作? Session 数据保留在服务端,而为了标识具体 Session 信息指向 ...
- GoldenGate12.3中新增的Parallel Replicat (PR)介绍
Parallel Replicat介绍 在OGG 12.3.0.1中新增的一项特性parallel replicat(并行投递),相对于传统的投递和集成投递(integrated replicat), ...
- CentOS 6.5优化开机启动服务
使用chkconfig命令列举出所有服务,配合管道筛选出开机默认启动的服务,再去掉level0(关机).level4(无意义)和level6(重启)的显示,使结果更直观. chkconfig | gr ...
- 【Alpha】Scrum Meeting 3
目录 简介: 工作内容: 工作修改: 燃尽图: 难点: 后期任务: 签入记录 团队讨论照片: 简介: 地点:J1-316 时间:4月3日星期四,晚上七点 会议目的:讨论大家此次的分工 工作内容: 陈治 ...
- Codeforces 333E Summer Earnings - bitset
题目传送门 传送门I 传送门II 传送门III 题目大意 给定平面上的$n$个点,以三个不同点为圆心画圆,使得圆两两没有公共部分(相切不算),问最大的半径. 显然答案是三点间任意两点之间的距离的最小值 ...
- bzoj2124: 等差子序列线段树+hash
bzoj2124: 等差子序列线段树+hash 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2124 思路 找大于3的等差数列其实就是找等于 ...
- oracle 根据出生日期计算年龄的年月日
select years,months,abs( trunc( newer_date- add_months( older_date,years*12+months ) ) ) days from ( ...