目录:

一、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. windows程序设计 获取显示器分辨率

    我的显示器分辨率 /*--------------------------------------------------------------------------- scrsize.c -- ...

  2. .Net 多线程 (1) Task

    多线程是一种有效提高程序工作效率的方法.当然为了效率需要使用更多的cpu,内存等资源. 并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机,如果串行,一个队列使用一台咖啡机,那么哪怕前 ...

  3. linux sar的使用

    sar(System Activity Reporter系统活动情况报告)是目前Linux上最为全面的系统性能分析工具之一,可以从多个方面对系统的活动进行报告,包括:文件的读写情况.系统调用的使用情况 ...

  4. json字符串 转Java List 简单方法

    JSONArray jsonArr = JSONArray.fromObject(jsonStr); List<Map<String,Object>> listMap = (L ...

  5. 【Python游戏编程01--初步认识pygame】

    一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.允许你在 Python 程序中创建功能丰富的游戏和多媒体程序,Pygame 是一个高 ...

  6. 虚拟主机、VPS、ECS云服务器 区别

    在阿里云上买了个云服务器. ssh命令都没通,找服务端同事帮我看,说我买错了.应该买ECS. 1.虚拟主机 虚拟主机就是利用虚拟化的技术,将一台服务器划分出一定大小的空间,每个空间都给予单独的 FTP ...

  7. svn版本备份和恢复注意事项

    转帖的,因为我经常要用到,所以也在我的博客上记录一下:  注意:备份不备份日志,你想备份日志就要单独在客户端备了,具体步骤百度上都有 svn备份常用命令1.完全备份和增量备份svn.svnadmin  ...

  8. Bootstrap3基础 page-header 标题下加分割线

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  9. (转) Ensemble Methods for Deep Learning Neural Networks to Reduce Variance and Improve Performance

    Ensemble Methods for Deep Learning Neural Networks to Reduce Variance and Improve Performance 2018-1 ...

  10. Learning-MySQL【2】:MySQL存储引擎及数据库的操作管理

    一.存储引擎 存储引擎实际上就是如何存储数据.如何为存储的数据建立索引和如何更新.查询数据.存储引擎也可以称为表类型. MySQL提供了插件式(pluggable)的存储引擎,存储引擎是基于表的.同一 ...