ServiceManager的啟動
ServiceManager作為Android系統(tǒng)服務的管理者,同時提供注冊、獲取系統(tǒng)服務等功能。它是由init進程啟動的,作為守護進程運行。
<frameworks/native/cmds/servicemanager/servicemanager.rc>
service servicemanager /system/bin/servicemanager
class core
user system
group system readproc
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
writepid /dev/cpuset/system-background/tasks
ServiceManager的運行
int main()
{
struct binder_state *bs;
// 打開binder,分配用于接收binder數(shù)據(jù)的地址空間(128K)
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
// 注冊為上下文(服務)管理者
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
......
// 進入binder消息循環(huán),處理binder請求
binder_loop(bs, svcmgr_handler);
return 0;
}
打開binder

下面從binder_open開始分析
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
// 打開binder設備文件,最終調(diào)用binder_open,請參考binder驅動
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
......
// 檢查binder驅動協(xié)議版本,避免用戶態(tài)與binder驅動使用的協(xié)議不一致
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
fprintf(stderr,
"binder: kernel driver version (%d) differs from user space version (%d)\n",
vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
bs->mapsize = mapsize;
// 分配用于接收binder數(shù)據(jù)的地址空間,最終調(diào)用binder_mmap,請參考binder驅動
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
return bs;
......
}
注冊為服務管理者

下面從binder_become_context_manager開始分析
int binder_become_context_manager(struct binder_state *bs)
{
// 直接調(diào)用ioctl進入binder驅動
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
下面看binder驅動的binder_ioctl處理BINDER_SET_CONTEXT_MGR請求.
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
// 進程的binder_proc
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
// ubuf = 0
void __user *ubuf = (void __user *)arg;
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
trace_binder_ioctl(cmd, arg);
......
binder_lock(__func__);
// 獲取當前線程的binder_thread
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
......
case BINDER_SET_CONTEXT_MGR:
// 注冊為上下文管理者
ret = binder_ioctl_set_ctx_mgr(filp);
if (ret)
goto err;
break;
......
}
......
}
先分析binder_get_thread的實現(xiàn)
static struct binder_thread *binder_get_thread(struct binder_proc *proc)
{
struct binder_thread *thread = NULL;
struct rb_node *parent = NULL;
struct rb_node **p = &proc->threads.rb_node;
// 以當前線程的pid為key搜索紅黑樹
while (*p) {
parent = *p;
thread = rb_entry(parent, struct binder_thread, rb_node);
if (current->pid < thread->pid)
p = &(*p)->rb_left;
else if (current->pid > thread->pid)
p = &(*p)->rb_right;
else
break;
}
// 當前線程對應的binder_thread不存在,創(chuàng)建
if (*p == NULL) {
thread = kzalloc(sizeof(*thread), GFP_KERNEL);
if (thread == NULL)
return NULL;
binder_stats_created(BINDER_STAT_THREAD);
thread->proc = proc;
thread->pid = current->pid;
init_waitqueue_head(&thread->wait);
INIT_LIST_HEAD(&thread->todo);
// 添加到binder_proc管理的binder線程紅黑樹中
rb_link_node(&thread->rb_node, parent, p);
rb_insert_color(&thread->rb_node, &proc->threads);
thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
thread->return_error = BR_OK;
thread->return_error2 = BR_OK;
}
return thread;
}
下面看binder_ioctl_set_ctx_mgr的實現(xiàn)
static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
int ret = 0;
// 進程的binder_proc
struct binder_proc *proc = filp->private_data;
// 線程的uid
kuid_t curr_euid = current_euid();
if (binder_context_mgr_node != NULL) {
pr_err("BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto out;
}
ret = security_binder_set_context_mgr(proc->tsk);
if (ret < 0)
goto out;
if (uid_valid(binder_context_mgr_uid)) {
if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
from_kuid(&init_user_ns, curr_euid),
from_kuid(&init_user_ns,
binder_context_mgr_uid));
ret = -EPERM;
goto out;
}
} else {
binder_context_mgr_uid = curr_euid;
}
// 創(chuàng)建binder_node對象,保存到全局變量binder_context_mgr_node
binder_context_mgr_node = binder_new_node(proc, 0, 0);
if (binder_context_mgr_node == NULL) {
ret = -ENOMEM;
goto out;
}
// 增加引用計數(shù)
binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
out:
return ret;
}
下面看binder_new_node的實現(xiàn)
static struct binder_node *binder_new_node(struct binder_proc *proc,
binder_uintptr_t ptr,
binder_uintptr_t cookie)
{
// 對于binder_context_mgr_node,ptr和cookie均為0
struct rb_node **p = &proc->nodes.rb_node;
struct rb_node *parent = NULL;
struct binder_node *node;
// 以ptr為key搜索binder_node紅黑樹
while (*p) {
parent = *p;
node = rb_entry(parent, struct binder_node, rb_node);
if (ptr < node->ptr)
p = &(*p)->rb_left;
else if (ptr > node->ptr)
p = &(*p)->rb_right;
else
return NULL;
}
// 創(chuàng)建binder_node
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL)
return NULL;
binder_stats_created(BINDER_STAT_NODE);
// 添加到binder_proc的binder_node紅黑樹中
rb_link_node(&node->rb_node, parent, p);
rb_insert_color(&node->rb_node, &proc->nodes);
node->debug_id = ++binder_last_id;
node->proc = proc;
node->ptr = ptr;
node->cookie = cookie;
node->work.type = BINDER_WORK_NODE;
INIT_LIST_HEAD(&node->work.entry);
INIT_LIST_HEAD(&node->async_todo);
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"%d:%d node %d u%016llx c%016llx created\n",
proc->pid, current->pid, node->debug_id,
(u64)node->ptr, (u64)node->cookie);
return node;
}
進入binder消息循環(huán),處理binder請求

下面從binder_loop開始分析
// binder_write_read為用戶態(tài)與binder驅動數(shù)據(jù)交互的控制結構體
struct binder_write_read {
binder_size_t write_size; // 用戶態(tài)發(fā)給binder驅動的命令數(shù)據(jù)大小
binder_size_t write_consumed; // binder驅動消耗的數(shù)據(jù)的大小
binder_size_t write_buffer; // 命令數(shù)據(jù)buffer地址
binder_size_t read_size; // 用于接收binder驅動返回的命令數(shù)據(jù)的buffer大小
binder_size_t read_consumed; // binder驅動返回給用戶態(tài)的命令數(shù)據(jù)大小
binder_size_t read_buffer; // 接收binder驅動返回的命令數(shù)據(jù)的buffer地址
}
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
// 向binder驅動發(fā)送命令協(xié)議BC_ENTER_LOOPER
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
// binder線程進入睡眠,等待客戶端的請求
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
......
// 處理客戶端的請求,如服務注冊、獲取等
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
......
}
}
首先看binder驅動處理BC_ENTER_LOOPER
int binder_write(struct binder_state *bs, void *data, size_t len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len; // len = 4
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data; // data中存放BC_ENTER_LOOPER
bwr.read_size = 0; // read_size為0,binder線程不會等待
bwr.read_consumed = 0;
bwr.read_buffer = 0;
// 向binder驅動發(fā)送ioctl命令BINDER_WRITE_READ
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n",
strerror(errno));
}
return res;
}
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
......
switch (cmd) {
case BINDER_WRITE_READ:
// 調(diào)用binder_ioctl_write_read處理BINDER_WRITE_READ
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
if (ret)
goto err;
break;
......
}
......
}
下面分析binder_ioctl_write_read
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg; // 用戶態(tài)bwr地址
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto out;
}
// 用戶態(tài)數(shù)據(jù)拷貝至內(nèi)核態(tài)
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
......
if (bwr.write_size > 0) {
// 處理用戶態(tài)發(fā)送的命令協(xié)議數(shù)據(jù)
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
// 當前read_size = 0
if (bwr.read_size > 0) {
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
......
// 內(nèi)核態(tài)bwr拷貝至用戶態(tài)
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
out:
return ret;
}
下面分析binder_thread_write處理命令協(xié)議數(shù)據(jù)
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;
// buffer中存放BC_ENTER_LOOPER命令協(xié)議
// *consumed為0
// size為4
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) {
// 從用戶態(tài)地址中讀取命令協(xié)議
if (get_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
trace_binder_command(cmd);
// 更新binder狀態(tài)
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
binder_stats.bc[_IOC_NR(cmd)]++;
proc->stats.bc[_IOC_NR(cmd)]++;
thread->stats.bc[_IOC_NR(cmd)]++;
}
switch (cmd) {
......
// 處理BC_ENTER_LOOPER
case BC_ENTER_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_ENTER_LOOPER\n",
proc->pid, thread->pid);
if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
proc->pid, thread->pid);
}
// 修改binder線程looper標志
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
......
}
*consumed = ptr - buffer;
}
return 0;
}
binder驅動處理命令協(xié)議BC_ENTER_LOOPER只是修改binder線程的looper標志,然后返回用戶態(tài)。下面回到binder_loop分析binder線程進入睡眠,等待客戶端的請求的過程。
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg; // 用戶態(tài)bwr地址
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto out;
}
// 用戶態(tài)數(shù)據(jù)拷貝至內(nèi)核態(tài)
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
......
// 此時bwr.write_size為0
if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
if (bwr.read_size > 0) {
// 調(diào)用binder_thread_read處理請求,如果沒有請求binder線程進入睡眠等待狀態(tài)
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
......
}
下面分析binder_thread_read
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)
{
// 用戶態(tài)read_buffer
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
int ret = 0;
int wait_for_proc_work;
if (*consumed == 0) {
// 向read_buffer中放空操作返回協(xié)議
if (put_user(BR_NOOP, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
}
retry:
// binder線程沒有工作
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);
......
// 修改binder線程looper標志
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (wait_for_proc_work)
// 增加binder_proc中空閑的binder線程計數(shù)
proc->ready_threads++;
binder_unlock(__func__);
trace_binder_wait_for_work(wait_for_proc_work,
!!thread->transaction_stack,
!list_empty(&thread->todo));
if (wait_for_proc_work) {
if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED))) {
binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
proc->pid, thread->pid, thread->looper);
wait_event_interruptible(binder_user_error_wait,
binder_stop_on_user_error < 2);
}
binder_set_nice(proc->default_priority);
if (non_block) {
if (!binder_has_proc_work(prc, thread))
ret = -EAGAIN;
} else
// binder線程進入睡眠,等待binder_has_proc_work(proc, thread)為true
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
......
}
......
}
Native層ServiceManager代理對象(BpServiceManager)的獲取
參見binder之服務注冊