目录:

一、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

Android : 跟我学Binder --- (3) C程序示例-LMLPHP

注: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;

Android : 跟我学Binder --- (3) C程序示例-LMLPHP

二、编写程序

  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-

05-06 11:42