Android Binder------ServiceManager启动分析
- int main(int argc, char **argv)
- {
- //记录serviceManager的状态
- struct binder_state *bs;
- void *svcmgr = BINDER_SERVICE_MANAGER;
- //用于打开binder设备 用于打开设备 后把设备映射到内存时申请的内存大小128*1024
- bs = binder_open(*);
- //注册自身为上下文管理者(context_manager)
- if (binder_become_context_manager(bs)) {
- ALOGE("cannot become context manager (%s)\n", strerror(errno));
- return -;
- }
- svcmgr_handle = svcmgr;
- //loop无线循环,等待接收IPC同请求
- binder_loop(bs, svcmgr_handler);
- return ;
- }
2 bind_open函数。用来打开binder设备。 call
by1
- struct binder_state *binder_open(unsigned mapsize)
- {
- struct binder_state *bs;
- bs = malloc(sizeof(*bs));
- if (!bs) {
- errno = ENOMEM;
- return ;
- }
- bs->fd = open("/dev/binder", O_RDWR);//打开binder设备
- if (bs->fd < ) {
- fprintf(stderr,"binder: cannot open device (%s)\n",
- strerror(errno));
- goto fail_open;
- }
- bs->mapsize = mapsize;//bs是用来保存open 和mmap的返回信息
- bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, );//进行内存映射,返回的映射区的起始地址给bs->mapped
- if (bs->mapped == MAP_FAILED) {//映射失败吹里逻辑
- fprintf(stderr,"binder: cannot map device (%s)\n",
- strerror(errno));
- goto fail_map;
- }
- /* TODO: check version */
- return bs;
- fail_map://映射失败的 goto处。
- close(bs->fd);
- fail_open://打开设备失败的goto处。
- free(bs);
- return ;
3.设置上下文Manager call by1
- int binder_become_context_manager(struct binder_state *bs)
- {
- return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, );
- //直接用ioctl函数( 提供了一种获得设备信息和向设备发送控制参数的手段)来让设备Binder设置上下文
- }
- void binder_loop(struct binder_state *bs, binder_handler func)
- {
- int res;
- struct binder_write_read bwr;
- unsigned readbuf[];
- bwr.write_size = ;
- bwr.write_consumed = ;
- bwr.write_buffer = ;
- //设置事务类型,Binder Command 为 BC_ENTER_LOOPER
- readbuf[] = BC_ENTER_LOOPER;
- //在binder_write中调用了ioctl函数,调用Binder设备的函数,标志serviceManager进入的Loop 状态。
- binder_write(bs, readbuf, sizeof(unsigned));
- for (;;) {
- bwr.read_size = sizeof(readbuf);
- bwr.read_consumed = ;
- bwr.read_buffer = (unsigned) readbuf;
- //每次循环都进入Binder设备的缓冲区中,看看是否有IPC请求。
- res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
- if (res < ) {
- ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
- break;
- }
- //对获取的结果进行解析。
- res = binder_parse(bs, , readbuf, bwr.read_consumed, func);
- if (res == ) {
- ALOGE("binder_loop: unexpected reply?!\n");
- break;
- }
- if (res < ) {
- ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
- break;
- }
- }
- }
5.把返回的数据进行解析 call by 4
- int binder_parse(struct binder_state *bs, struct binder_io *bio,
- uint32_t *ptr, uint32_t size, binder_handler func)
- {
- int r = ;
- uint32_t *end = ptr + (size / );
- while (ptr < end) {
- uint32_t cmd = *ptr++;
- #if TRACE
- fprintf(stderr,"%s:\n", cmd_name(cmd));
- #endif
- switch(cmd) {
- case BR_NOOP:
- break;
- case BR_TANSACTION_COMPLETE:
- break;R
- case BR_INCREFS:
- case BR_ACQUIRE:
- case BR_RELEASE:
- case BR_DECREFS:
- #if TRACE
- fprintf(stderr," %08x %08x\n", ptr[], ptr[]);
- #endif
- ptr += ;
- break;
- case BR_TRANSACTION: {
- struct binder_txn *txn = (void *) ptr;
- if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
- ALOGE("parse: txn too small!\n");
- return -;
- }
- binder_dump_txn(txn);
- if (func) {
- unsigned rdata[/];
- struct binder_io msg;//
- struct binder_io reply;//回复信息的结构体
- int res;
- bio_init(&reply, rdata, sizeof(rdata), );//数据的初始化
- bio_init_from_txn(&msg, txn);
- //fun函数中会进行事务最终的处理,add Service find service 注册 service
- res = 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 ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
- ALOGE("parse: reply too small!\n");
- return -;
- }
- binder_dump_txn(txn);
- if (bio) {
- bio_init_from_txn(bio, txn);
- bio = ;
- } else {
- /* todo FREE BUFFER */
- }
- ptr += (sizeof(*txn) / sizeof(uint32_t));
- r = ;
- break;
6 在该函数中会对事务进行相应的出路 callby 5
- 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;
- int allow_isolated;
- // ALOGI("target=%p code=%d pid=%d uid=%d\n",
- // txn->target, txn->code, txn->sender_pid, txn->sender_euid);
- if (txn->target != svcmgr_handle)
- return -;
- // 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);
- s = bio_get_string16(msg, &len);
- if ((len != (sizeof(svcmgr_id) / )) ||
- memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
- fprintf(stderr,"invalid id %s\n", str8(s));
- return -;
- }
- switch(txn->code) {
- case SVC_MGR_GET_SERVICE:
- case SVC_MGR_CHECK_SERVICE:
- s = bio_get_string16(msg, &len);
- //查找相应的service
- ptr = do_find_service(bs, s, len, txn->sender_euid);//call 7
- if (!ptr)
- break;
- bio_put_ref(reply, ptr);
- return ;
- case SVC_MGR_ADD_SERVICE:
- s = bio_get_string16(msg, &len);
- ptr = bio_get_ref(msg);
- allow_isolated = bio_get_uint32(msg) ? : ;
- //add service 进行service的注册。
- if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
- return -;
- break;
- case SVC_MGR_LIST_SERVICES: {
- unsigned n = bio_get_uint32(msg);
- si = svclist;
- while ((n-- > ) && si)
- si = si->next;
- if (si) {
- bio_put_string16(reply, si->name);
- return ;
- }
- return -;
- }
- default:
- ALOGE("unknown code %d\n", txn->code);
- return -;
- }
- bio_put_uint32(reply, );
- return ;
- }
7 查找service call by 6
- void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
- {
- struct svcinfo *si;
- //最终的查找函数了
- si = find_svc(s, len);
- // ALOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
- if (si && si->ptr) {
- if (!si->allow_isolated) {
- // If this service doesn't allow access from isolated processes,
- // then check the uid to see if it is isolated.
- unsigned appid = uid % AID_USER;
- if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
- return ;
- }
- }
- return si->ptr;
- } else {
- return ;
- }
- }
8 最终的findservice动作是在这里结束 callby
7
- struct svcinfo *find_svc(uint16_t *s16, unsigned len)
- {
- struct svcinfo *si;//svcinfo就是一个链表的node数据结构,存放了service的信息
- //svclist存放了所有已经注册的了的 service,这里进行遍历,通过mencmp进行匹配
- for (si = svclist; si; si = si->next) {
- if ((len == si->len) &&
- !memcmp(s16, si->name, len * sizeof(uint16_t))) {
- return si;
- }
- }
- return ;
- }
9 注册服务 callby
6
- int do_add_service(struct binder_state *bs,
- uint16_t *s, unsigned len,
- void *ptr, unsigned uid, int allow_isolated)
- {
- struct svcinfo *si;
- //ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr,
- // allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
- if (!ptr || (len == ) || (len > ))
- return -;
- //验证UID是否有添加服务的权限。
- if (!svc_can_register(uid, s)) {
- ALOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
- str8(s), ptr, uid);
- return -;
- }
- //判断服务是否存在,存在就不进行重复注册了。
- si = find_svc(s, len);
- if (si) {
- if (si->ptr) {
- ALOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
- str8(s), ptr, uid);
- svcinfo_death(bs, si);
- }
- si->ptr = ptr;
- } else {//不存在则为心注册的服务分配内存
- si = malloc(sizeof(*si) + (len + ) * sizeof(uint16_t));
- if (!si) {//分配内存失败
- ALOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
- str8(s), ptr, uid);
- return -;
- }
- //为注册的服务的 scvinfo 结构体赋值,
- si->ptr = ptr;
- si->len = len;
- memcpy(si->name, s, (len + ) * sizeof(uint16_t));
- si->name[len] = '\0';
- si->death.func = svcinfo_death;
- si->death.ptr = si;
- si->allow_isolated = allow_isolated;
- //可见list的插入可以头插入法。
- si->next = svclist;
- svclist = si;
- }
- binder_acquire(bs, ptr);
- binder_link_to_death(bs, ptr, &si->death);
- return ;
- }
- int svc_can_register(unsigned uid, uint16_t *name)
- {
- unsigned n;
- if ((uid == ) || (uid == AID_SYSTEM))//uid=0为root用户, AID_SYSTEM为系统 service
- return ;
- //遍历允许注册service的进程数组
- for (n = ; n < sizeof(allowed) / sizeof(allowed[]); n++)
- if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
- return ;
- return ;
- }
允许注册服务的进程列表(如果自定义rom自己增加系统服务,就可以在这里增加以获得权限啦)
- static struct {
- unsigned uid;
- const char *name;
- } allowed[] = {
- { AID_MEDIA, "media.audio_flinger" },
- { AID_MEDIA, "media.player" },
- { AID_MEDIA, "media.camera" },
- { AID_MEDIA, "media.audio_policy" },
- { AID_DRM, "drm.drmManager" },
- { AID_NFC, "nfc" },
- { AID_RADIO, "radio.phone" },
- { AID_RADIO, "radio.sms" },
- { AID_RADIO, "radio.phonesubinfo" },
- { AID_RADIO, "radio.simphonebook" },
- /* TODO: remove after phone services are updated: */
- { AID_RADIO, "phone" },
- { AID_RADIO, "sip" },
- { AID_RADIO, "isms" },
- { AID_RADIO, "iphonesubinfo" },
- { AID_RADIO, "simphonebook" },
- { AID_MEDIA, "common_time.clock" },
- { AID_MEDIA, "common_time.config" },
- };
Android Binder------ServiceManager启动分析的更多相关文章
- Android Zygote进程启动分析
dvm,app进程,linux进程三者关系 DVM指 dalivk 的虚拟机.每一个 Android 应用程序都在它自己的进程中运行,都拥有一个独立的 Dalvik 虚拟机实例.而每一个 DVM 都是 ...
- 【转载】Android App应用启动分析与优化
前言: 昨晚新版本终于发布了,但是还是记得有测试反馈app启动好长时间也没进入app主页,所以今天准备加个班总结一下App启动那些事! app的启动方式: 1.)冷启动 当启动应用时,后台没有该应用 ...
- 图解Android - Zygote, System Server 启动分析
Init 是所有Linux程序的起点,而Zygote于Android,正如它的英文意思,是所有java程序的'孵化池'(玩过星际虫族的兄弟都晓得的).用ps 输出可以看到 >adb shell ...
- Android应用程序启动过程(二)分析
本文依据Android6.0源码,从点击Launcher图标,直至解析到MainActivity#OnCreate()被调用. Launcher简析 Launcher也是个应用程序,不过是个特殊的应用 ...
- Android Binder分析二:Natvie Service的注冊
这一章我们通过MediaPlayerService的注冊来说明怎样在Native层通过binder向ServiceManager注冊一个service,以及client怎样通过binder向Servi ...
- Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析 1. Binder驱动情景分析 1.1 进程间通信三要素 源 目的:handle表示"服务",即向 ...
- Android ContentProvider 启动分析
对于 ContentProvider 还不是很熟悉的同学,可以阅读上一篇 Android ContentProvider 基本原理和使用详解.本文主要是对 contentProvider 的源码进行分 ...
- Android Activity Deeplink启动来源获取源码分析
一.前言 目前有很多的业务模块提供了Deeplink服务,Deeplink简单来说就是对外部应用提供入口. 针对不同的跳入类型,app可能会选择提供不一致的服务,这个时候就需要对外部跳入的应用进行区分 ...
- Android 4.2启动代码分析(一)
Android系统启动过程分析 Android系统的框架架构图如下(来自网上): Linux内核启动之后----->就到Android的Init进程 ----->进而启动Android ...
随机推荐
- POJ 1269 Intersecting Lines(几何)
题目链接 题意 : 给你两条线段的起点和终点,一共四个点,让你求交点坐标,如果这四个点是共线的,输出“LINE”,如果是平行的就输出“NONE”. 思路 : 照着ZN留下的模板果然好用,直接套上模板了 ...
- NODE.JS的基本系统模块操作样例
就练练手, 嘿嘿,说不定,写服务器脚本也可以哟. console.log('Currently executing file is ' + __filename); console.log('It i ...
- Android ViewPager的每个页面的显示与销毁的时机
大家在用viewPager的时候要创建一个pagerAdapter对象,用于给viewPager设置页面的. viewPager里面有一个container容器. viewPager的容器缓存3个显示 ...
- c缺陷与陷阱笔记-第七章 可移植性代码
1.移位运算符 如果被移位的对象长度是n位,那么移位计数必须>=0,并且<n,例如对于1个32位的数,移位运算n<<31和n<<0是OK的,n<<32和 ...
- APP,webapp 设计相关资料汇集区
(1).@2x iPhone3GS时代,我们为一个应用提供图标(或按钮提供贴图),只需要icon.png.针对现在的iPhone4~6 Retina显示屏,需要制作额外的@2x高分辨率版本. 例如在i ...
- Java Web开发 之小张老师总结GET和POST区别
get和post区别1.传输方式不同,get在request-line中传输(即在URL中传输).post在request-line及 request-body中传输(可认为隐藏传输)2.get传输长 ...
- H264码流解析及NALU
ffmpeg 从mp4上提取H264的nalu http://blog.csdn.net/gavinr/article/details/7183499 639 /* bitstream fil ...
- CentOS7.1配置远程桌面
网上看了很多资料,完全是乱的. 我使用的是CentOS7.1的系统.我的要求是windows的客户机可以远程访问CentOS系统. 1,首先需要检查一下服务器是否已经安装了VNC服务,检查服务器的是否 ...
- Servlet课程0426(十一)Servlet Cookie实现两周内不用重复登录
Welcome.java //登录界面 package com.tsinghua; import javax.servlet.http.*; import java.io.*; import java ...
- 查看32bit的ARM(比如ARMv7)反汇编
1.使用./arm-eabi-as test.S -o test.o编译 2.使用./arm-eabi-objdump -d test.o反汇编