通過上面的代碼我們知道service manager的核心服務(wù)主要有4個(gè)
- do_add_service()函數(shù):注冊(cè)服務(wù)
- do_find_service()函數(shù):查找服務(wù)
- binder_link_to_death()函數(shù):結(jié)束服務(wù)
- binder_send_reply()函數(shù):將注冊(cè)結(jié)果返回給Binder驅(qū)動(dòng)
1 do_add_service()函數(shù) 注冊(cè)服務(wù)
//service_manager.c 194行
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
if (!handle || (len == 0) || (len > 127))
return -1;
//權(quán)限檢查
if (!svc_can_register(s, len, spid)) {
return -1;
}
//服務(wù)檢索
si = find_svc(s, len);
if (si) {
if (si->handle) {
svcinfo_death(bs, si); //服務(wù)已注冊(cè)時(shí),釋放相應(yīng)的服務(wù)
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
//內(nèi)存不足,無法分配足夠內(nèi)存
return -1;
}
si->handle = handle;
si->len = len;
//內(nèi)存拷貝服務(wù)信息
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
// svclist保存所有已注冊(cè)的服務(wù)
si->next = svclist;
svclist = si;
}
//以BC_ACQUIRE命令,handle為目標(biāo)的信息,通過ioctl發(fā)送給binder驅(qū)動(dòng)
binder_acquire(bs, handle);
//以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通過ioctl發(fā)送給binder驅(qū)動(dòng),主要用于清理內(nèi)存等收尾工作。
binder_link_to_death(bs, handle, &si->death);
return 0;
}
注冊(cè)服務(wù)部分主要分塊內(nèi)容:
- svc_can_register:檢查權(quán)限:檢查selinux權(quán)限是否滿足
- find_svc:服務(wù)檢索,根據(jù)服務(wù)名來查詢匹配的服務(wù);
- svcinfo_death:釋放服務(wù),當(dāng)查詢到已存在的同名的服務(wù),則先清理該服務(wù)信息,再講當(dāng)前的服務(wù)加入到服務(wù)列表svclist;
1.1 svc_can_register()函數(shù)
//service_manager.c 110行
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
{
const char *perm = "add";
//檢查selinux權(quán)限是否滿足
return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
}
1.2 svcinfo_death()函數(shù)
//service_manager.c 153行
void svcinfo_death(struct binder_state *bs, void *ptr)
{
struct svcinfo *si = (struct svcinfo* ) ptr;
if (si->handle) {
binder_release(bs, si->handle);
si->handle = 0;
}
}
3 bio_get_ref()函數(shù)
// framework/native/cmds/servicemanager/binder.c 627行
uint32_t bio_get_ref(struct binder_io *bio)
{
struct flat_binder_object *obj;
obj = _bio_get_obj(bio);
if (!obj)
return 0;
if (obj->type == BINDER_TYPE_HANDLE)
return obj->handle;
return 0;
}
2 do_find_service() 查找服務(wù)
//service_manager.c 170行
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
//具體查詢相應(yīng)的服務(wù)
struct svcinfo *si = find_svc(s, len);
if (!si || !si->handle) {
return 0;
}
if (!si->allow_isolated) {
uid_t appid = uid % AID_USER;
//檢查該服務(wù)是否允許孤立于進(jìn)程而單獨(dú)存在
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
//服務(wù)是否滿足于查詢條件
if (!svc_can_find(s, len, spid)) {
return 0;
}
/返回結(jié)點(diǎn)中的ptr,這個(gè)ptr是binder中對(duì)應(yīng)的binder_ref.des
return si->handle;
}
主要就是查詢目標(biāo)服務(wù),并返回該服務(wù)所對(duì)應(yīng)的handle
2.1 find_svc()函數(shù)
//service_manager.c 140行
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
struct svcinfo *si;
for (si = svclist; si; si = si->next) {
//當(dāng)名字完全一致,則返回查詢到的結(jié)果
if ((len == si->len) &&
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
}
return NULL;
}
在svclist服務(wù)列表中,根據(jù)服務(wù)名遍歷查找是否已經(jīng)注冊(cè)。當(dāng)服務(wù)已經(jīng)存在svclist,則返回相應(yīng)的服務(wù)名,否則返回null。
在svcmgr_handler中當(dāng)執(zhí)行完do_find_service()函數(shù)后,會(huì)調(diào)用bio_put_ref()函數(shù),將handle封裝到reply.
bio_put_ref()函數(shù)
// framework/native/cmds/servicemanager/binder.c 505行
void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
//構(gòu)造了一個(gè)flat_binder_object
struct flat_binder_object *obj;
if (handle)
obj = bio_alloc_obj(bio);
else
obj = bio_alloc(bio, sizeof(*obj));
if (!obj)
return;
obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
obj->type = BINDER_TYPE_HANDLE; //返回的是HANDLE類型
//以service manager的身份回應(yīng)給kernel driver,ptr就是handler對(duì)應(yīng)的ref索引值 1,2,3,4,5,6等
obj->handle = handle;
obj->cookie = 0;
}
這個(gè)段代碼也不復(fù)雜,就是根據(jù)handle來判斷分別執(zhí)行bio_alloc_obj()函數(shù)和bio_alloc()函數(shù)
bio_alloc_obj()函數(shù)
// framework/native/cmds/servicemanager/binder.c 468 行
static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
{
struct flat_binder_object *obj;
obj = bio_alloc(bio, sizeof(*obj));
if (obj && bio->offs_avail) {
bio->offs_avail--;
*bio->offs++ = ((char*) obj) - ((char*) bio->data0);
return obj;
}
bio->flags |= BIO_F_OVERFLOW;
return NULL;
}
bio_alloc()函數(shù)
// framework/native/cmds/servicemanager/binder.c 437 行
static void *bio_alloc(struct binder_io *bio, size_t size)
{
size = (size + 3) & (~3);
if (size > bio->data_avail) {
bio->flags |= BIO_F_OVERFLOW;
return NULL;
} else {
void *ptr = bio->data;
bio->data += size;
bio->data_avail -= size;
return ptr;
}
}
3 binder_link_to_death() 函數(shù)
// framework/native/cmds/servicemanager/binder.c 305行
void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
{
struct {
uint32_t cmd;
struct binder_handle_cookie payload;
} __attribute__((packed)) data;
data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
data.payload.handle = target;
data.payload.cookie = (uintptr_t) death;
binder_write(bs, &data, sizeof(data));
}
binder_write和前面的binder_write一樣,進(jìn)入Binder driver后,直接調(diào)用binder_thread_write,處理BC_REQUEST_DEATH_NOTIFICATION命令。其中binder_ioctl_write_read()函數(shù),前面面已經(jīng)講解過了。這里就不詳細(xì)講解了
3.1 binder_thread_write() 函數(shù)
//kernel/drivers/android/binder.c 2248行
static int binder_thread_write(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed)
{
uint32_t cmd;
struct binder_context *context = proc->context;
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error == BR_OK) {
//獲取命令
get_user(cmd, (uint32_t __user *)ptr);
switch (cmd) {
//**** 省略部分代碼 ****
// 注冊(cè)死亡通知
case BC_REQUEST_DEATH_NOTIFICATION:
case BC_CLEAR_DEATH_NOTIFICATION: {
uint32_t target;
void __user *cookie;
struct binder_ref *ref;
struct binder_ref_death *death;
//獲取taget
get_user(target, (uint32_t __user *)ptr);
ptr += sizeof(uint32_t);
/獲取death
get_user(cookie, (void __user * __user *)ptr); /
ptr += sizeof(void *);
//拿到目標(biāo)服務(wù)的binder_ref
ref = binder_get_ref(proc, target);
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
//已設(shè)死亡通知
if (ref->death) {
break;
}
death = kzalloc(sizeof(*death), GFP_KERNEL);
INIT_LIST_HEAD(&death->work.entry);
death->cookie = cookie;
ref->death = death;
//當(dāng)目標(biāo)服務(wù)所在進(jìn)程已死,則發(fā)送死亡通知
if (ref->node->proc == NULL) {
//當(dāng)前線程為binder線程,則直接添加到當(dāng)前線程的TODO隊(duì)列
ref->death->work.type = BINDER_WORK_DEAD_BINDER;
if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
list_add_tail(&ref->death->work.entry, &thread->todo);
} else {
list_add_tail(&ref->death->work.entry, &proc->todo);
wake_up_interruptible(&proc->wait);
}
}
} else {
...
}
} break;
//**** 省略部分代碼 ****
}
//**** 省略部分代碼 ****
return 0;
}
- 此方法中的proc,thread都是指當(dāng)前的servicemanager進(jìn)程信息,此時(shí)TODO隊(duì)列有數(shù)據(jù),則進(jìn)入binder_thread_read。
- 那么問題來了,哪些場(chǎng)景會(huì)向隊(duì)列增加BINDER_WORK_READ_BINDER事物?那邊是當(dāng)binder所在進(jìn)程死亡后,會(huì)調(diào)用binder_realse方法,然后調(diào)用binder_node_release這個(gè)過程便會(huì)發(fā)出死亡通知的回調(diào)。
3.2 binder_thread_read() 函數(shù)
static int binder_thread_read(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
...
//只有當(dāng)前線程todo隊(duì)列為空,并且transaction_stack也為空,才會(huì)開始處于當(dāng)前進(jìn)程的事務(wù)
if (wait_for_proc_work) {
...
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
...
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
//加鎖
binder_lock(__func__);
if (wait_for_proc_work)
//空閑的binder線程減1
proc->ready_threads--;
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
//從todo隊(duì)列拿出前面放入的binder_work, 此時(shí)type為BINDER_WORK_DEAD_BINDER
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct binder_work,
entry);
} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
w = list_first_entry(&proc->todo, struct binder_work,
entry);
}
switch (w->type) {
case BINDER_WORK_DEAD_BINDER: {
struct binder_ref_death *death;
uint32_t cmd;
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
...
else
//進(jìn)入此分支
cmd = BR_DEAD_BINDER;
//拷貝用戶空間
put_user(cmd, (uint32_t __user *)ptr);
ptr += sizeof(uint32_t);
//此處的cookie是前面?zhèn)鬟f的svcinfo_death
put_user(death->cookie, (binder_uintptr_t __user *)ptr);
ptr += sizeof(binder_uintptr_t);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
...
} else
list_move(&w->entry, &proc->delivered_death);
if (cmd == BR_DEAD_BINDER)
goto done;
} break;
}
}
...
return 0;
}
- 將命令BR_DEAD_BINDER寫到用戶空間,此處的cookie是前面?zhèn)鬟f的svcinfo_death。當(dāng)binder_loop下一次執(zhí)行binder_parse的過程便會(huì)處理該消息。
- binder_parse()函數(shù)和svcinfo_death()函數(shù)上面已經(jīng)說明了,這里就不詳細(xì)說明了。
3.3 binder_release() 函數(shù)
//frameworks/native/cmds/servicemanager/binder.c 297行
void binder_release(struct binder_state *bs, uint32_t target)
{
uint32_t cmd[2];
cmd[0] = BC_RELEASE;
cmd[1] = target;
binder_write(bs, cmd, sizeof(cmd));
}
向Binder Driver寫入BC_RELEASE命令,最終進(jìn)入Binder Driver后執(zhí)行binder_dec_ref(ref,1) 來減少binder node的引用。
4 binder_send_reply() 函數(shù) 將注冊(cè)結(jié)果返回給Binder驅(qū)動(dòng)
//frameworks/native/cmds/servicemanager/binder.c 170行
void binder_send_reply(struct binder_state *bs,
struct binder_io *reply,
binder_uintptr_t buffer_to_free,
int status) {
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data;
//free buffer命令
data.cmd_free = BC_FREE_BUFFER;
data.buffer = buffer_to_free;
//replay命令
data.cmd_reply = BC_REPLY;
data.txn.target.ptr = 0;
data.txn.cookie = 0;
data.txn.code = 0;
if (status) {
data.txn.flags = TF_STATUS_CODE;
data.txn.data_size = sizeof(int);
data.txn.offsets_size = 0;
data.txn.data.ptr.buffer = (uintptr_t) & status;
data.txn.data.ptr.offsets = 0;
} else {
data.txn.flags = 0;
data.txn.data_size = reply -> data - reply -> data0;
data.txn.offsets_size = ((char*)reply -> offs)-((char*)reply -> offs0);
data.txn.data.ptr.buffer = (uintptr_t) reply -> data0;
data.txn.data.ptr.offsets = (uintptr_t) reply -> offs0;
}
//向Binder驅(qū)動(dòng)通信
binder_write(bs, & data, sizeof(data));
}
執(zhí)行binder_parse方法,先調(diào)用svcmgr_handler()函數(shù),然后再執(zhí)行binder_send_reply過程,該過程會(huì)調(diào)用binder_write進(jìn)入binder驅(qū)動(dòng)后,將BC_FREE_BUFFER和BC_REPLY命令協(xié)議發(fā)送給Binder驅(qū)動(dòng),向Client端發(fā)送reply,其中data數(shù)據(jù)區(qū)中保存的是TYPE為HANDLE。