• Binder 驱动分析C(一)示例代码


    提前声明:此文章为学习后的一些心得体会,若有错误请指出,如有侵权请联系。

    Binder驱动不是单独拿出来分析,是结合在Android中的使用情景分析的,我们在此是结合Android Service来分析Binder驱动:

    主要分析以下几部分:

      1.服务的注册过程;

      2.服务的获取和使用过程;

      3.transaction stack机制(replay和双向服务)。

    在Android系统中,Binder的使用是很常见的,无论是java层、C++层还是C层使用Binder系统都是通过底层的Binder驱动。

      Binder的作用就是为了提供进程间通信的一种方法,Android中的service类似于网络通信中C/S模式,Binder的作用与http/UDP作用类似,只是提供的数据的通道;

      网络通讯中只要应用层序解析数据包的协议一致,我们就可以在不同的平台(windows、linux、mac)之间通信;

      Android中的service也一样,只要上层服务和客户端解析数据的协议一致,则C层、C++层和Java层都可以通过Binder进行通信。

    我们在此分析由易到难,先分析C层的,然后分析C++和Java层的。

    先贴出C层分析的代码:

    可以参考 framework/native/cmds/servicemanager目录下的代码编写测试程序,在此我贴出简化版的的示例,仅用于分析;

    一共有6个文件:

      binder.c binder.h service_manager.c test_client.c test_server.c test_server.h

      其中前3个文件可以在Android系统源码中找到。

    1 #ifndef _TEST_SERVER_H
    2 #define _TEST_SERVER_H
    3 
    4 #define HELLO_SVR_CMD_SAYHELLO     1
    5 #define HELLO_SVR_CMD_SAYHELLO_TO  2
    6 
    7 #endif // _TEST_SERVER_H
    test_server.h
      1 int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
      2 {
      3     int status;
      4     unsigned iodata[512/4];
      5     struct binder_io msg, reply;
      6 
      7     bio_init(&msg, iodata, sizeof(iodata), 4);
      8     bio_put_uint32(&msg, 0);  // strict mode header
      9     bio_put_string16_x(&msg, SVC_MGR_NAME);
     10     bio_put_string16_x(&msg, name);
     11     bio_put_obj(&msg, ptr);
     12 
     13     if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
     14         return -1;
     15 
     16     status = bio_get_uint32(&reply);
     17 
     18     binder_done(bs, &msg, &reply);
     19 
     20     return status;
     21 }
     22 
     23 void sayhello(void)
     24 {
     25     static int cnt = 0;
     26     fprintf(stderr, "say hello : %d
    ", ++cnt);
     27 }
     28 
     29 
     30 int sayhello_to(char *name)
     31 {
     32     static int cnt = 0;
     33     fprintf(stderr, "say hello to %s : %d
    ", name, ++cnt);
     34     return cnt;
     35 }
     36 
     37 int hello_service_handler(struct binder_state *bs,
     38                    struct binder_transaction_data *txn,
     39                    struct binder_io *msg,
     40                    struct binder_io *reply)
     41 {
     42     uint16_t *s;
     43     char name[512];
     44     size_t len;
     45     uint32_t handle;
     46     uint32_t strict_policy;
     47     int i;
     48 
     49     strict_policy = bio_get_uint32(msg);
     50 
     51     switch(txn->code) {
     52     case HELLO_SVR_CMD_SAYHELLO:
     53         sayhello();
     54         bio_put_uint32(reply, 0); 
     55         return 0;
     56 
     57     case HELLO_SVR_CMD_SAYHELLO_TO:
     58         s = bio_get_string16(msg, &len);  //"IHelloService"
     59         s = bio_get_string16(msg, &len);  // name
     60         if (s == NULL) {
     61             return -1;
     62         }
     63         for (i = 0; i < len; i++)
     64             name[i] = s[i];
     65         name[i] = '';
     66 
     67         i = sayhello_to(name);
     68 
     69         bio_put_uint32(reply, 0); /* no exception */
     70         bio_put_uint32(reply, i);
     71         
     72         break;
     73 
     74     default:
     75         fprintf(stderr, "unknown code %d
    ", txn->code);
     76         return -1;
     77     }
     78 
     79     return 0;
     80 }
     81 
     82 int test_server_handler(struct binder_state *bs,
     83                    struct binder_transaction_data *txn,
     84                    struct binder_io *msg,
     85                    struct binder_io *reply)
     86 {
     87     int (*handler)(struct binder_state *bs,
     88                    struct binder_transaction_data *txn,
     89                    struct binder_io *msg,
     90                    struct binder_io *reply);
     91 
     92     handler = (int (*)(struct binder_state *bs,
     93                    struct binder_transaction_data *txn,
     94                    struct binder_io *msg,
     95                    struct binder_io *reply))txn->target.ptr;
     96     
     97     return handler(bs, txn, msg, reply);
     98 }
     99 
    100 int main(int argc, char **argv)
    101 {
    102     int fd;
    103     struct binder_state *bs;
    104     uint32_t svcmgr = BINDER_SERVICE_MANAGER;
    105     uint32_t handle;
    106     int ret;
    107 
    108     bs = binder_open(128*1024);
    109     if (!bs) {
    110         fprintf(stderr, "failed to open binder driver
    ");
    111         return -1;
    112     }
    113 
    114     /* add service */
    115     ret = svcmgr_publish(bs, svcmgr, "hello", hello_service_handler);
    116     if (ret) {
    117         fprintf(stderr, "failed to publish hello service
    ");
    118         return -1;
    119     }
    120     
    121     binder_set_maxthreads(bs, 10);
    122 
    123     binder_loop(bs, test_server_handler);
    124 
    125     return 0;
    126 }
    test_server.c
    uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
    {
        uint32_t handle;
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // 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 0;
    
        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[512/4];
        struct binder_io msg, reply;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, "IHelloService");
    
        if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO))
            return ;
        
        binder_done(g_bs, &msg, &reply);
        
    }
    
    int sayhello_to(char *name)
    {
        unsigned iodata[512/4];
        struct binder_io msg, reply;
        int ret;
        int exception;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, "IHelloService");
    
        bio_put_string16_x(&msg, name);
    
        if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO_TO))
            return 0;
        
        exception = bio_get_uint32(&reply);
        if (exception)
            ret = -1;
        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 < 2){
            fprintf(stderr, "Usage:
    ");
            fprintf(stderr, "%s hello
    ", argv[0]);
            fprintf(stderr, "%s hello <name>
    ", argv[0]);
            return -1;
        }
    
        bs = binder_open(128*1024);
        if (!bs) {
            fprintf(stderr, "failed to open binder driver
    ");
            return -1;
        }
        g_bs = bs;
    
    
        /* get service */
        handle = svcmgr_lookup(bs, svcmgr, "hello");
        g_hello_handle = handle;
    
        /* send data to server */
        if (argc == 2) {
            sayhello();
        } else if (argc == 3) {
            ret = sayhello_to(argv[2]);
            fprintf(stderr, "get ret of sayhello_to = %d
    ", ret);        
        }
        
        binder_release(bs, handle);
        return 0;
    }
    test_client.c

    为了避免后面晕头转向,先简单介绍一下Binder驱动相关的数据结构:

    图片中完整的语句是:Handle是服务进程A对客户进程B提供的服务S的引用在客户进程B中的Index;

    binder_proc

    针对每个进程,使用binder_proc结构体描述,由于每个进程可能创建多个线程,所以其中的threads成员以红黑树管理着所有的线程;

    其中的nodes成员管理着所有的binder_node结构,binder_node结构代表每个被注册的服务,这个成员一般是服务进程使用;

    其中的refs_by_desc和refs_by_node成员管理着所有的binder_refs结构,binder_refs结构代表获取到的服务的引用,这个成员一般是客户进程使用;

    binder_node 

    针对每个被注册的服务,驱动程序会创建binder_node结构,用于描述注册的服务;

    proc成员指向创建对应服务的进程;

    cookie和ptr可以理解为服务的私有数据;

    binder_refs

    客户进程获取服务时,不是直接获取到服务所对应的binder_node结构,而是获取到它的引用,引用使用binder_refs结构描述;

    其中的proc成员指向获取服务的进程;

    node成员指向期望得到的服务所对应的binder_node结构;

    desc为在某个进程中获取到的服务的索引值,该值只与在该进程中获取服务的先后有关;

    注意:只有服务管理者(SM)的desc为0,其他服务的desc都是非0正整数。

    一、服务的注册过程分析:

     

  • 相关阅读:
    STS IDE 个性化修改
    tomcat发布web项目,支持域名
    执行 maven 命令 报错Unable to add module to the current project as it is not of packaging type 'pom'[转]
    从数组中返回最大长度的所有子数组
    springboot 1.5.x 使用tomcat8设置cookie的domain以dot开头报错
    tomcat服务器配置字符集为utf-8-彻底解决中文乱码问题
    通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明
    Java原理之HashMap
    你应该知道的JAVA面试题
    sql 置顶功能的查询
  • 原文地址:https://www.cnblogs.com/hei-da-mi/p/7883576.html
Copyright © 2020-2023  润新知