Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發之serviceManager分析

Android開發之serviceManager分析

編輯:關於Android編程

Android 開發之serviceManager分析
        在Android系統中用到最多的通信機制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驅動程序組成。其中Client、Service和ServiceManager運行在用戶空間,而Binder驅動程序運行在內核空間。核心組件就是Binder驅動程序了,而ServiceManager提供輔助管理的功能,無論是Client還是Service進行通信前首先要和ServiceManager取得聯系。而ServiceManager是一個守護進程,負責管理Server並向Client提供查詢Server的功能。

 

[html] 
在init.rc中servicemanager是作為服務啟動的,而且是在zygote啟動之前 
service servicemanager /system/bin/servicemanager 
    class core 
    user system 
    group system 
    critical 
    onrestart restart zygote 
    onrestart restart media 
    onrestart restart surfaceflinger 
    onrestart restart drm 

在init.rc中servicemanager是作為服務啟動的,而且是在zygote啟動之前
service servicemanager /system/bin/servicemanager
 class core
 user system
 group system
 critical
 onrestart restart zygote
 onrestart restart media
 onrestart restart surfaceflinger
 onrestart restart drm
源碼位置:frameworks/base/cmds/servicemanager/service_manager.c

[html] 
int main(int argc, char** argv) 

    struct binder_state *bs; 
    void* svcmgr = BINDER_SERVICE_MANAGER; 
     
    bs = binder_open(128*1024); 
     
    binder_become_context_manager(bs); 
     
    svcmgr_handle = svcmgr; 
     
    binder_loop(bs, svcmgr_handler); 
     
    return 0; 

int main(int argc, char** argv)
{
 struct binder_state *bs;
 void* svcmgr = BINDER_SERVICE_MANAGER;
 
 bs = binder_open(128*1024);
 
 binder_become_context_manager(bs);
 
 svcmgr_handle = svcmgr;
 
 binder_loop(bs, svcmgr_handler);
 
 return 0;
}
 這裡main函數主要有三個功能:
1)打開Binder設備文件
 首先我們來看看這個struct binder_state結構體
 struct binder_state
 {
         int fd;   // 文件描述符,打開/dev/binder設備
         void* mapped;  // 把設備文件/dev/binder映射到進程空間的起始地址
         unsigned mapsize; // 映射內存空間的大小
 };
 
 宏:#define BINDER_SERVICE_MANAGER ((void*)0)
 表示ServiceManager對應的句柄為0,表面自己是服務器管理者。其他的Server進程句柄值都是大於0的。

[html
struct binder_state* binder_open(unsigned mapsize) 

    struct binder_state* bs; 
    bs = malloc(sizeof(*bs)); 
    bs->fd = open("/dev/binder", O_RDWR); 
    bs->mapsize = mapsize; 
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 
    return bs; 
}    
這裡主要就是打開Binder設備,映射128K的內存地址空間 

struct binder_state* binder_open(unsigned mapsize)
{
 struct binder_state* bs;
 bs = malloc(sizeof(*bs));
 bs->fd = open("/dev/binder", O_RDWR);
 bs->mapsize = mapsize;
 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
 return bs;

這裡主要就是打開Binder設備,映射128K的內存地址空間

2)告訴Binder驅動程序自己是Binder上下文管理者


[html]
<SPAN style="COLOR: #000000">int binder_become_context_manager(struct binder_state *bs) 

    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); 

調用驅動程序設置這個進程為管理者BINDER_SET_CONTEXT_MGR</SPAN> 

int binder_become_context_manager(struct binder_state *bs)
{
 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
調用驅動程序設置這個進程為管理者BINDER_SET_CONTEXT_MGR3)進入一個無線循環,充當server角色,等待Client的請求

[html] 
void binder_loop(struct binder_state bs, binder_handler func) 

    struct binder_write_read bwr; 
    unsigned readbuf[32]; 
     
    bwr.write_size = 0; 
    bwr.write_consumed = 0; 
    bwr.write_buffer = 0; 
    readbuf[0] = BC_ENTER_LOOPER;   // 設置事件類型為LOOPER 
    // 調用ioctl函數,通知Binder設備servicemanager開始進入loop狀態 
    binder_write(bs, readbuf, sizeof(unsigned)); 
     
    for(;;) { 
        bwr.read_size = sizeof(readbuf); 
        bwr.read_consumed = 0; 
        bwr.read_buffer = (unsigned)readbuf; 
        // 進入Binder設備緩沖區,檢查是否有IPC請求 
        ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 
        // 對於請求調用binder_parse進行解析處理 
        binder_parse(bs, 0, readbuf, bwr.read_consumed, func); 
    } 

 
這裡我們看下struct binder_write_read這個結構體: 
struct binder_write_read{ 
    signed long write_size; 
    signed long write_consumed; // bytes consumed by driver 
    unsigned long write_buffer; 
    signed long read_size; 
    signed long read_consumed;  // bytes consumed by driver 
    unsigned long read_buffer; 
}; 
 
int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr,  
            uint32_t size, binder_handler func) 

    uint32_t *end = ptr + (size / 4);    
    while(ptr < end) { 
        uint32_t cmd = *ptr++; 
        switch(cmd) { 
        ...... 
        case BR_TRANSACTOIN:{   // 收到請求進行處理 
            struct bindeer_txn *txn = (void*) ptr; 
            if(func) { 
                unsigned rdata[256/4]; 
                struct binder_io msg; 
                struct binder_io reply; 
                bio_init(&reply, rdata, sizeof(rdata), 4); 
                bio_init_from_txn(&msg, txn); 
                ret = func(bs, txn, &msg, &reply); 
                binder_send_reply(bs, &reply, txn->data, res); 
            } 
            ptr += sizeof(*txn) / sizeof(uint32_t); 
            break; 
        } 
        case BR_REPLY: {    // 回復的請求處理 
            struct binder_txn *txn = (void*)ptr; 
            if(bio) { 
                bio_init_from_txn(bio, txn); 
                bio = 0; 
            }else { 
                // to free buffer 
            } 
            ptr += sizeof(*txn) / sizeof(uint32_t); 
            r = 0; 
            break; 
        } 
        case BR_DEAD_BINDER: { 
            struct binder_death* death = (void*)*ptr++; 
            death->func(bs, death->ptr); 
            break; 
        } 
        ... 
        } 
    } 
    return r; 

/*這裡binder_parse函數首先將binder讀取過來的請求數據轉化為bindeer_txn結構體,然後根據這個結構體 
初始化binder_io msg,交給回調函數svcmgr_handler處理,同時返回一個binder_io reply,最後將 
這個reply發送返回給客戶端。*/ 
struc binder_io 

    char* data;     // 指向read/write的數據 
    uint32_t *offs;     // 偏移數組 
    uint32_t data_avail;    // data中有效字節長  
    uint32_t offs_avail;    // 偏移數組中有效字節長 
    char* data0;        // data起始地址 
    uint32_t *offs0;    // 偏移buffer的起始地址 
    uint32_t flags; 
    uint32_t unused; 
}; 
最終調用的處理函數還是svcmgr_handler,終於要開始出來請求數據了: 
 
int svcmgr_handler(struct binder_state* bs, struct binder_txn *txn,  
        struct binder_io *msg, struct binder_io *reply) 

    struct svcinfo *si; 
    uint16_t *s; 
    unsigned len; 
    void* ptr; 
    uint32_t strict_policy; 
     
    if(txn->target != svcmgr_handler) 
        return -1;  // 首先判斷這個消息的是不是發給自己的 
    strict_policy = bio_get_uint32(msg); 
    s = bio_get_string16(msg, &len); 
    switch(txn->code) { 
    case SVC_MGR_GET_SERVICE: 
    case SVC_MGR_CHECK_SERVICE: 
        s = bio_get_string16(msg, &len);    // 獲取要查詢的服務名字 
        ptr = do_find_service(bs, s, len);  // 根據服務名字查找鏈表 
        bio_put_ref(reply, ptr); 
        return 0; 
    case SVC_MGR_ADD_SERVICE:           // 添加服務 
        s = bio_get_string16(msg, &len); 
        ptr = bio_get_ref(msg); 
        do_add_service(bs, s, len, ptr, txn->sender_euid); 
        bio_put_uint32(reply, 0);   // 告知添加成功 
        return 0; 
    .... 
    } 
    return 0; 

void binder_loop(struct binder_state bs, binder_handler func)
{
 struct binder_write_read bwr;
 unsigned readbuf[32];
 
 bwr.write_size = 0;
 bwr.write_consumed = 0;
 bwr.write_buffer = 0;
 readbuf[0] = BC_ENTER_LOOPER; // 設置事件類型為LOOPER
 // 調用ioctl函數,通知Binder設備servicemanager開始進入loop狀態
 binder_write(bs, readbuf, sizeof(unsigned));
 
 for(;;) {
  bwr.read_size = sizeof(readbuf);
  bwr.read_consumed = 0;
  bwr.read_buffer = (unsigned)readbuf;
  // 進入Binder設備緩沖區,檢查是否有IPC請求
  ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
  // 對於請求調用binder_parse進行解析處理
  binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
 }
}

這裡我們看下struct binder_write_read這個結構體:
struct binder_write_read{
 signed long write_size;
 signed long write_consumed; // bytes consumed by driver
 unsigned long write_buffer;
 signed long read_size;
 signed long read_consumed; // bytes consumed by driver
 unsigned long read_buffer;
};

int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr,
   uint32_t size, binder_handler func)
{
 uint32_t *end = ptr + (size / 4); 
 while(ptr < end) {
  uint32_t cmd = *ptr++;
  switch(cmd) {
  ......
  case BR_TRANSACTOIN:{ // 收到請求進行處理
   struct bindeer_txn *txn = (void*) ptr;
   if(func) {
    unsigned rdata[256/4];
    struct binder_io msg;
    struct binder_io reply;
    bio_init(&reply, rdata, sizeof(rdata), 4);
    bio_init_from_txn(&msg, txn);
    ret = func(bs, txn, &msg, &reply);
    binder_send_reply(bs, &reply, txn->data, res);
   }
   ptr += sizeof(*txn) / sizeof(uint32_t);
   break;
  }
  case BR_REPLY: {  // 回復的請求處理
   struct binder_txn *txn = (void*)ptr;
   if(bio) {
    bio_init_from_txn(bio, txn);
    bio = 0;
   }else {
    // to free buffer
   }
   ptr += sizeof(*txn) / sizeof(uint32_t);
   r = 0;
   break;
  }
  case BR_DEAD_BINDER: {
   struct binder_death* death = (void*)*ptr++;
   death->func(bs, death->ptr);
   break;
  }
  ...
  }
 }
 return r;
}
/*這裡binder_parse函數首先將binder讀取過來的請求數據轉化為bindeer_txn結構體,然後根據這個結構體
初始化binder_io msg,交給回調函數svcmgr_handler處理,同時返回一個binder_io reply,最後將
這個reply發送返回給客戶端。*/
struc binder_io
{
 char* data;  // 指向read/write的數據
 uint32_t *offs;  // 偏移數組
 uint32_t data_avail; // data中有效字節長
 uint32_t offs_avail; // 偏移數組中有效字節長
 char* data0;  // data起始地址
 uint32_t *offs0; // 偏移buffer的起始地址
 uint32_t flags;
 uint32_t unused;
};
最終調用的處理函數還是svcmgr_handler,終於要開始出來請求數據了:

int svcmgr_handler(struct binder_state* bs, struct binder_txn *txn,
  struct binder_io *msg, struct binder_io *reply)
{
 struct svcinfo *si;
 uint16_t *s;
 unsigned len;
 void* ptr;
 uint32_t strict_policy;
 
 if(txn->target != svcmgr_handler)
  return -1; // 首先判斷這個消息的是不是發給自己的
 strict_policy = bio_get_uint32(msg);
 s = bio_get_string16(msg, &len);
 switch(txn->code) {
 case SVC_MGR_GET_SERVICE:
 case SVC_MGR_CHECK_SERVICE:
  s = bio_get_string16(msg, &len); // 獲取要查詢的服務名字
  ptr = do_find_service(bs, s, len); // 根據服務名字查找鏈表
  bio_put_ref(reply, ptr);
  return 0;
 case SVC_MGR_ADD_SERVICE:    // 添加服務
  s = bio_get_string16(msg, &len);
  ptr = bio_get_ref(msg);
  do_add_service(bs, s, len, ptr, txn->sender_euid);
  bio_put_uint32(reply, 0); // 告知添加成功
  return 0;
 ....
 }
 return 0;
}首先我們得看看Binder是怎麼組織Binder傳遞消息的數據結構的,根據前面我們知道調用Binder驅動
的時候我們獲得了一個void* ptr結構體,強制轉化為binder_txn *txn,然後根據這個txn我們獲得了
Binder的輸入輸出結構體binder_io *bio。最後我們不管是處理請求還是發送回復都是處理這個bio結構。
而我們的Binder通信的binder結構是由binder_object來組織的,指向binder_io結構裡面data。
首先我們得看看Binder是怎麼組織Binder傳遞消息的數據結構的,根據前面我們知道調用Binder驅動
的時候我們獲得了一個void* ptr結構體,強制轉化為binder_txn *txn,然後根據這個txn我們獲得了
Binder的輸入輸出結構體binder_io *bio。最後我們不管是處理請求還是發送回復都是處理這個bio結構。
而我們的Binder通信的binder結構是由binder_object來組織的,指向binder_io結構裡面data。

[html]
struct binder_object 

    uint32_t type; 
    uint32_t flags; 
    void* pointer; 
    void* cookie; 
}; 

struct binder_object
{
 uint32_t type;
 uint32_t flags;
 void* pointer;
 void* cookie;
};上面的binder_object結構體內容依次對應著我們代碼中的:
bio_get_uint32(msg);
bio_get_string16(msg, &len);
bio_get_string16(msg, &len);
bio_get_ref(msg);
上面的binder_object結構體內容依次對應著我們代碼中的:
bio_get_uint32(msg);
bio_get_string16(msg, &len);
bio_get_string16(msg, &len);
bio_get_ref(msg);

當客戶端需要添加服務的時候:SVC_MGR_ADD_SERVICE
1)首先調用bio_get_string16()從binder_io中獲得服務名字。
2)調用bio_get_ref()從binder_io中獲得服務的binder實體struct binder_object

[html]
void* bio_get_ref(struct binder_io* bio) 

    struct binder_object* obj; 
    obj = _bio_get_obj(bio);// 這個函數最終調用的是   void* ptr = bio->data;    
    return obj->pointer; 

void* bio_get_ref(struct binder_io* bio)
{
 struct binder_object* obj;
 obj = _bio_get_obj(bio);// 這個函數最終調用的是 void* ptr = bio->data; 
 return obj->pointer;
}3)調用do_add_service()將上面的Binder實體引用寫到服務中,再通過名字加到全局鏈表中


[html]
int do_add_service(struct binder_state* bs, uint16_t *s, unsigned len, void* ptr, unsigned uid) 

    struct svcinfo *si; 
     
    svc_can_register(uid, s);   // 檢查權限 
     
    si = find_svc(s, len); 
    // 根據名字查找鏈表,判斷是否已經存在 
    si = malloc(sizeof(*si) + (len+1)*sizeof(uin16_t)); 
    si->ptr = ptr;   //指向上面的binder_object的pointer也就是Binder實體 
    memcpy(si->name, s, (len+1)*sizeof(uint16_t)); 
    si->name[len] = '\0'; 
    si->death.func = svcinfo_death; 
    si->death.ptr = si; 
    si->next = svclist; 
    svclist = si; 
     
    binder_acquire(bs, ptr); 
    binder_link_to_death(bs, ptr, &si->death); 
    return 0; 

int do_add_service(struct binder_state* bs, uint16_t *s, unsigned len, void* ptr, unsigned uid)
{
 struct svcinfo *si;
 
 svc_can_register(uid, s); // 檢查權限
 
 si = find_svc(s, len);
 // 根據名字查找鏈表,判斷是否已經存在
 si = malloc(sizeof(*si) + (len+1)*sizeof(uin16_t));
 si->ptr = ptr; //指向上面的binder_object的pointer也就是Binder實體
 memcpy(si->name, s, (len+1)*sizeof(uint16_t));
 si->name[len] = '\0';
 si->death.func = svcinfo_death;
 si->death.ptr = si;
 si->next = svclist;
 svclist = si;
 
 binder_acquire(bs, ptr);
 binder_link_to_death(bs, ptr, &si->death);
 return 0;
}
當客戶端需要查詢服務的時候:
1)bio_get_string16() 獲得服務名字
2)do_find_service() 遍歷全局鏈表svclist,根據服務名字找到對應的服務並返回。
2)bio_put_ref(reply, ptr);這裡reply就是需要返回給客戶端的結構體,而ptr就是指向目標Binder實體。

[html] 
void bio_put_ref(struct binder_io* bio, void* ptr) 

    struct binder_object *obj; 
    obj = bio_alloc(bio); 
    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; 
    obj->type = BINDER_TYPE_HANDLE; 
    obj->pointer = ptr; 
    obj->cookie = 0; 

void bio_put_ref(struct binder_io* bio, void* ptr)
{
 struct binder_object *obj;
 obj = bio_alloc(bio);
 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 obj->type = BINDER_TYPE_HANDLE;
 obj->pointer = ptr;
 obj->cookie = 0;
}回到binder_parse函數裡面,執行:binder_send_reply()通知Binder驅動程序

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved