目录:

一、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程序示例的更多相关文章

  1. Android : 跟我学Binder --- (6) JAVA实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  2. Android : 跟我学Binder --- (5) C++实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  3. Android : 跟我学Binder --- (4) 驱动情景分析

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  4. Android : 跟我学Binder --- (2) AIDL分析及手动实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  5. Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  6. 9.1 Binder系统_C程序示例_框架分析和编写程序

    IPC : Inter-Process Communication, 进程间通信 A进程把数据原原本本的发给B,这就是IPC RPC : Remote Procedure Call, 远程过程调用 A ...

  7. 写给 Android 应用工程师的 Binder 原理剖析

    写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...

  8. 深入理解Android IPC机制之Binder机制

    Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...

  9. 【Android - IPC】之Binder机制简介

    参考资料: 1.<Android开发艺术探索>第二章2.3.3 Binder 2.[Android Binder设计与实现-设计篇] 3.[Android Binder机制介绍] 1. 什 ...

随机推荐

  1. centos crash debug

    https://www.dedoimedo.com/computers/crash.html#mozTocId484074 http://people.redhat.com/anderson/cras ...

  2. spring quartz执行两次问题

    解决quartz定时任务被触发两次的问题: 其中<Host/>告诉tomcat,在启动的时候加载webapps下的所有项目工程文件,<Context/>又让tomcat再加载了 ...

  3. Lucene的深入

    Lucene创建索引 第一.创建文档对象 第二.创建Field对象(各种类型)整数String.Text.Long.Float.Double等... Field对象 包含三大属性:是否分词,是否索引, ...

  4. Python IO内核交互了解

    注:Unix \ Linux 环境下的network IO   用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系 ...

  5. git分散式版本管理系统,从安装到基本使用

    首先,当然是安装git了,不用寻思,官网下载即可 https://git-scm.com/downloads 第二是设置账户,鼠标右键,选择git bush,在命令窗口中进行设置 git config ...

  6. log4net架构、配置、使用

    架构说明 架构说明 上图是官方文档的提供的代码组织. Log4net的核心组件有: Logger, Appender, Filter, Layout, Object Render, Logger介绍 ...

  7. AJAX缓存清理

    Ajax页面缓存是ajax处理数据时对一些重复相同数据进行一个缓存操作,这样从另一个层面对于我们来讲是非常的不错了,但有时我们并不希望它缓存要如何处理呢?下面我们一起来看看关于页面缓存问题分析与解决, ...

  8. Learning-Python【15】:内置函数

    截止到Python版本3.6.2,一共为我们提供了68个内置函数.它们就是Python提供的直接可以拿来使用的所有函数. 这个表的顺序是按照首字母的排列顺序来的,都混乱的堆在一起.比如,oct和bin ...

  9. Learning-Python【19】:Python常用模块(2)—— os、sys、shutil

    os模块:与操作系统相关的模块 import os # 获取当前的工作目录 print(os.getcwd()) # 切换工作目录 os.chdir(r'E:\Python\test') print( ...

  10. js同步、异步、回调的执行顺序以及闭包的理解

    首先,记住同步第一.异步第二.回调最末的口诀 公式表达:同步=>异步=>回调 看一道经典的面试题: for (var i = 0; i < 5; i++) { setTimeout( ...