Android Bander设计与实现 - 设计篇
摘要
Binder是Android系统进程间通信(IPC)方式之一。Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具有无可比拟的优势。深入了解Binder并将之与传统IPC做对比有助于我们深入领会进程间通信的实现和性能优化。本文将对Binder的设计细节做一个全面的阐述,首先通过介绍Binder通信模型和Binder通信协议了解Binder的设计需求;然后分别阐述Binder在系统不同部分的表述方式和起的作用;最后还会解释Binder在数据接收端的设计考虑,包括线程池管理,内存映射和等待队列管理等。通过本文对Binder的详细介绍以及与其它IPC通信方式的对比,读者将对Binder的优势和使用Binder作为Android主要IPC方式的原因有深入了解。
1 引言
IPC |
数据拷贝次数 |
共享内存 |
0 |
Binder |
1 |
Socket/管道/消息队列 |
2 |
2 面向对象的 Binder IPC
当然面向对象只是针对应用程序而言,对于Binder驱动和内核其它模块一样使用C语言实现,没有类和对象的概念。Binder驱动为面向对象的进程间通信提供底层支持。
3 Binder 通信模型
3.1 Binder 驱动
3.2 ServiceManager 与实名Binder
3.3 Client 获得实名Binder的引用
3.4 匿名 Binder
下图展示了参与Binder通信的所有角色,将在以后章节中一一提到。
4 Binder 协议
Binder协议基本格式是(命令+数据),使用ioctl(fd, cmd, arg)函数实现交互。命令由参数cmd承载,数据由参数arg承载,随cmd不同而不同。下表列举了所有命令及其所对应的数据:
命令 |
含义 |
arg |
BINDER_WRITE_READ |
该命令向Binder写入或读取数据。参数分为两段:写部分和读部分。如果write_size不为0就先将write_buffer里的数据写入Binder;如果read_size不为0再从Binder中读取数据存入read_buffer中。write_consumed和read_consumed表示操作完成时Binder驱动实际写入或读出的数据个数。 |
struct binder_write_read { signed long write_size; signed long write_consumed; unsigned long write_buffer; signed long read_size; signed long read_consumed; unsigned long read_buffer; }; |
BINDER_SET_MAX_THREADS |
该命令告知Binder驱动接收方(通常是Server端)线程池中最大的线程数。由于Client是并发向Server端发送请求的,Server端必须开辟线程池为这些并发请求提供服务。告知驱动线程池的最大值是为了让驱动发现线程数达到该值时不要再命令接收端启动新的线程。 |
int max_threads; |
BINDER_SET_CONTEXT_MGR |
将当前进程注册为SMgr。系统中同时只能存在一个SMgr。只要当前的SMgr没有调用close()关闭Binder驱动就不能有别的进程可以成为SMgr。 |
--- |
BINDER_THREAD_EXIT |
通知Binder驱动当前线程退出了。Binder会为所有参与Binder通信的线程(包括Server线程池中的线程和Client发出请求的线程)建立相应的数据结构。这些线程在退出时必须通知驱动释放相应的数据结构。 |
--- |
BINDER_VERSION |
获得Binder驱动的版本号。 |
--- |
4.1 BINDER_WRITE_READ 之写操作
cmd |
含义 |
arg |
BC_TRANSACTION |
BC_TRANSACTION用于Client向Server发送请求数据;BC_REPLY用于Server向Client发送回复(应答)数据。其后面紧接着一个binder_transaction_data结构体表明要写入的数据。 |
struct binder_transaction_data |
BC_ACQUIRE_RESULT |
暂未实现 |
--- |
BC_FREE_BUFFER |
释放一块映射的内存。Binder接收方通过mmap()映射一块较大的内存空间,Binder驱动基于这片内存采用最佳匹配算法实现接收数据缓存的动态分配和释放,满足并发请求对接收缓存区的需求。应用程序处理完这片数据后必须尽快使用该命令释放缓存区,否则会因为缓存区耗尽而无法接收新数据。 |
指向需要释放的缓存区的指针;该指针位于收到的Binder数据包中 |
BC_INCREFS |
这组命令增加或减少Binder的引用计数,用以实现强指针或弱指针的功能。 |
32位Binder引用号 |
BC_INCREFS_DONE |
第一次增加Binder实体引用计数时,驱动向Binder实体所在的进程发送BR_INCREFS, BR_ACQUIRE消息;Binder实体所在的进程处理完毕回馈BC_INCREFS_DONE,BC_ACQUIRE_DONE |
void *ptr:Binder实体在用户空间中的指针 void *cookie:与该实体相关的附加数据 |
BC_REGISTER_LOOPER |
这组命令同BINDER_SET_MAX_THREADS一道实现Binder驱动对接收方线程池管理。BC_REGISTER_LOOPER通知驱动线程池中一个线程已经创建了;BC_ENTER_LOOPER通知驱动该线程已经进入主循环,可以接收数据;BC_EXIT_LOOPER通知驱动该线程退出主循环,不再接收数据。 |
--- |
BC_REQUEST_DEATH_NOTIFICATION |
获得Binder引用的进程通过该命令要求驱动在Binder实体销毁得到通知。虽说强指针可以确保只要有引用就不会销毁实体,但这毕竟是个跨进程的引用,谁也无法保证实体由于所在的Server关闭Binder驱动或异常退出而消失,引用者能做的是要求Server在此刻给出通知。 |
uint32 *ptr; 需要得到死亡通知的Binder引用 void **cookie: 与死亡通知相关的信息,驱动会在发出死亡通知时返回给发出请求的进程。 |
BC_DEAD_BINDER_DONE |
收到实体死亡通知书的进程在删除引用后用本命令告知驱动。 |
void **cookie |
4.2 BINDER_WRITE_READ :从Binder读出数据
从Binder里读出的数据格式和向Binder中写入的数据格式一样,采用(消息ID+数据)形式,并且多条消息可以连续存放。下表列举了从Binder读出的命令字及其相应的参数:
消息 |
含义 |
参数 |
BR_ERROR |
发生内部错误(如内存分配失败) |
--- |
BR_OK |
操作完成 |
--- |
BR_SPAWN_LOOPER |
该消息用于接收方线程池管理。当驱动发现接收方所有线程都处于忙碌状态且线程池里的线程总数没有超过BINDER_SET_MAX_THREADS设置的最大线程数时,向接收方发送该命令要求创建更多线程以备接收数据。 |
--- |
BR_TRANSACTION |
这两条消息分别对应发送方的BC_TRANSACTION和BC_REPLY,表示当前接收的数据是请求还是回复。 |
binder_transaction_data |
BR_ACQUIRE_RESULT |
尚未实现 |
--- |
BR_DEAD_REPLY |
交互过程中如果发现对方进程或线程已经死亡则返回该消息 |
--- |
BR_TRANSACTION_COMPLETE |
发送方通过BC_TRANSACTION或BC_REPLY发送完一个数据包后,都能收到该消息做为成功发送的反馈。这和BR_REPLY不一样,是驱动告知发送方已经发送成功,而不是Server端返回请求数据。所以不管同步还是异步交互接收方都能获得本消息。 |
--- |
BR_INCREFS |
这一组消息用于管理强/弱指针的引用计数。只有提供Binder实体的进程才能收到这组消息。 |
void *ptr:Binder实体在用户空间中的指针 void *cookie:与该实体相关的附加数据 |
BR_DEAD_BINDER |
向获得Binder引用的进程发送Binder实体死亡通知书;收到死亡通知书的进程接下来会返回BC_DEAD_BINDER_DONE做确认。 |
void **cookie:在使用BC_REQUEST_DEATH_NOTIFICATION注册死亡通知时的附加参数。 |
BR_FAILED_REPLY |
如果发送非法引用号则返回该消息 |
--- |
4.3 struct binder_transaction_data :收发数据包结构
该结构是Binder接收/发送数据包的标准格式,每个成员定义如下:
表 5 Binder收发数据包结构:binder_transaction_data
成员 |
含义 |
union { size_t handle; void *ptr; } target; |
对于发送数据包的一方,该成员指明发送目的地。由于目的是在远端,所以这里填入的是对Binder实体的引用,存放在target.handle中。如前述,Binder的引用在代码中也叫句柄(handle)。 当数据包到达接收方时,驱动已将该成员修改成Binder实体,即指向Binder对象内存的指针,使用target.ptr来获得。该指针是接收方在将Binder实体传输给其它进程时提交给驱动的,驱动程序能够自动将发送方填入的引用转换成接收方Binder对象的指针,故接收方可以直接将其当做对象指针来使用(通常是将其reinterpret_cast成相应类)。 |
void *cookie; |
发送方忽略该成员;接收方收到数据包时,该成员存放的是创建Binder实体时由该接收方自定义的任意数值,做为与Binder指针相关的额外信息存放在驱动中。驱动基本上不关心该成员。 |
unsigned int code; |
该成员存放收发双方约定的命令码,驱动完全不关心该成员的内容。通常是Server端定义的公共接口函数的编号。 |
unsigned int flags; |
与交互相关的标志位,其中最重要的是TF_ONE_WAY位。如果该位置上表明这次交互是异步的,Server端不会返回任何数据。驱动利用该位来决定是否构建与返回有关的数据结构。另外一位TF_ACCEPT_FDS是出于安全考虑,如果发起请求的一方不希望在收到的回复中接收文件形式的Binder可以将该位置上。因为收到一个文件形式的Binder会自动为数据接收方打开一个文件,使用该位可以防止打开文件过多。 |
pid_t sender_pid; uid_t sender_euid; |
该成员存放发送方的进程ID和用户ID,由驱动负责填入,接收方可以读取该成员获知发送方的身份。 |
size_t data_size; |
该成员表示data.buffer指向的缓冲区存放的数据长度。发送数据时由发送方填入,表示即将发送的数据长度;在接收方用来告知接收到数据的长度。 |
size_t offsets_size; |
驱动一般情况下不关心data.buffer里存放什么数据,但如果有Binder在其中传输则需要将其相对data.buffer的偏移位置指出来让驱动知道。有可能存在多个Binder同时在数据中传递,所以须用数组表示所有偏移位置。本成员表示该数组的大小。 |
union { struct { const void *buffer; const void *offsets; } ptr; uint8_t buf[8]; } data; |
data.bufer存放要发送或接收到的数据;data.offsets指向Binder偏移位置数组,该数组可以位于data.buffer中,也可以在另外的内存空间中,并无限制。buf[8]是为了无论保证32位还是64位平台,成员data的大小都是8个字节。 |
5 Binder 的表述
考察一次Binder通信的全过程会发现,Binder存在于系统以下几个部分中:
· 应用程序进程:分别位于Server进程和Client进程中
· Binder驱动:分别管理为Server端的Binder实体和Client端的引用
· 传输数据:由于Binder可以跨进程传递,需要在传输数据中予以表述
在系统不同部分,Binder实现的功能不同,表现形式也不一样。接下来逐一探讨Binder在各部分所扮演的角色和使用的数据结构。
5.1 Binder 在应用程序中的表述
5.1.1 Binder 在Server端的表述 – Binder实体
5.1.2 Binder 在Client端的表述 – Binder引用
5.2 Binder 在传输数据中的表述
Binder可以塞在数据包的有效数据中越进程边界从一个进程传递给另一个进程,这些传输中的Binder用结构flat_binder_object表示,如下表所示:
表 6 Binder传输结构:flat_binder_object
成员 |
含义 |
unsigned long type |
表明该Binder的类型,包括以下几种: BINDER_TYPE_BINDER:表示传递的是Binder实体,并且指向该实体的引用都是强类型; BINDER_TYPE_WEAK_BINDER:表示传递的是Binder实体,并且指向该实体的引用都是弱类型; BINDER_TYPE_HANDLE:表示传递的是Binder强类型的引用 BINDER_TYPE_WEAK_HANDLE:表示传递的是Binder弱类型的引用 BINDER_TYPE_FD:表示传递的是文件形式的Binder,详见下节 |
unsigned long flags |
该域只对第一次传递Binder实体时有效,因为此刻驱动需要在内核中创建相应的实体节点,有些参数需要从该域取出: 第0-7位:代码中用FLAT_BINDER_FLAG_PRIORITY_MASK取得,表示处理本实体请求数据包的线程的最低优先级。当一个应用程序提供多个实体时,可以通过该参数调整分配给各个实体的处理能力。 第8位:代码中用FLAT_BINDER_FLAG_ACCEPTS_FDS取得,置1表示该实体可以接收其它进程发过来的文件形式的Binder。由于接收文件形式的Binder会在本进程中自动打开文件,有些Server可以用该标志禁止该功能,以防打开过多文件。 |
union { void *binder; signed long handle; }; |
当传递的是Binder实体时使用binder域,指向Binder实体在应用程序中的地址。 当传递的是Binder引用时使用handle域,存放Binder在进程中的引用号。 |
void *cookie; |
该域只对Binder实体有效,存放与该Binder有关的附加信息。 |
下表总结了当flat_binder_object结构穿过驱动时驱动所做的操作:
Binder 类型( type 域) |
在发送方的操作 |
在接收方的操作 |
BINDER_TYPE_BINDER BINDER_TYPE_WEAK_BINDER |
只有实体所在的进程能发送该类型的Binder。如果是第一次发送驱动将创建实体在内核中的节点,并保存binder,cookie,flag域。 |
如果是第一次接收该Binder则创建实体在内核中的引用;将handle域替换为新建的引用号;将type域替换为BINDER_TYPE_(WEAK_)HANDLE |
BINDER_TYPE_HANDLE BINDER_TYPE_WEAK_HANDLE |
获得Binder引用的进程都能发送该类型Binder。驱动根据handle域提供的引用号查找建立在内核的引用。如果找到说明引用号合法,否则拒绝该发送请求。 |
如果收到的Binder实体位于接收进程中:将ptr域替换为保存在节点中的binder值;cookie替换为保存在节点中的cookie值;type替换为BINDER_TYPE_(WEAK_)BINDER。 如果收到的Binder实体不在接收进程中:如果是第一次接收则创建实体在内核中的引用;将handle域替换为新建的引用号 |
BINDER_TYPE_FD |
验证handle域中提供的打开文件号是否有效,无效则拒绝该发送请求。 |
在接收方创建新的打开文件号并将其与提供的打开文件描述结构绑定。 |
5.2.1 文件形式的 Binder
5.3 Binder 在驱动中的表述
5.3.1 Binder 实体在驱动中的表述
驱动中的Binder实体也叫‘节点’,隶属于提供实体的进程,由struct binder_node结构来表示:
成员 |
含义 |
int debug_id; |
用于调试 |
struct binder_work work; |
当本节点引用计数发生改变,需要通知所属进程时,通过该成员挂入所属进程的to-do队列里,唤醒所属进程执行Binder实体引用计数的修改。 |
union { struct rb_node rb_node; struct hlist_node dead_node; }; |
每个进程都维护一棵红黑树,以Binder实体在用户空间的指针,即本结构的ptr成员为索引存放该进程所有的Binder实体。这样驱动可以根据Binder实体在用户空间的指针很快找到其位于内核的节点。rb_node用于将本节点链入该红黑树中。 销毁节点时须将rb_node从红黑树中摘除,但如果本节点还有引用没有切断,就用dead_node将节点隔离到另一个链表中,直到通知所有进程切断与该节点的引用后,该节点才可能被销毁。 |
struct binder_proc *proc; |
本成员指向节点所属的进程,即提供该节点的进程。 |
struct hlist_head refs; |
本成员是队列头,所有指向本节点的引用都链接在该队列里。这些引用可能隶属于不同的进程。通过该队列可以遍历指向该节点的所有引用。 |
int internal_strong_refs; |
用以实现强指针的计数器:产生一个指向本节点的强引用该计数就会加1。 |
int local_weak_refs; |
驱动为传输中的Binder设置的弱引用计数。如果一个Binder打包在数据包中从一个进程发送到另一个进程,驱动会为该Binder增加引用计数,直到接收进程通过BC_FREE_BUFFER通知驱动释放该数据包的数据区为止。 |
int local_strong_refs; |
驱动为传输中的Binder设置的强引用计数。同上。 |
void __user *ptr; |
指向用户空间Binder实体的指针,来自于flat_binder_object的binder成员 |
void __user *cookie; |
指向用户空间的附加指针,来自于flat_binder_object的cookie成员 |
unsigned has_strong_ref; unsigned pending_strong_ref; unsigned has_weak_ref; unsigned pending_weak_ref |
这一组标志用于控制驱动与Binder实体所在进程交互式修改引用计数 |
unsigned has_async_transaction; |
该成员表明该节点在to-do队列中有异步交互尚未完成。驱动将所有发送往接收端的数据包暂存在接收进程或线程开辟的to-do队列里。对于异步交互,驱动做了适当流控:如果to-do队列里有异步交互尚待处理则该成员置1,这将导致新到的异步交互存放在本结构成员 – asynch_todo队列中,而不直接送到to-do队列里。目的是为同步交互让路,避免长时间阻塞发送端。 |
unsigned accept_fds |
表明节点是否同意接受文件方式的Binder,来自flat_binder_object中flags成员的FLAT_BINDER_FLAG_ACCEPTS_FDS位。由于接收文件Binder会为进程自动打开一个文件,占用有限的文件描述符,节点可以设置该位拒绝这种行为。 |
int min_priority |
设置处理Binder请求的线程的最低优先级。发送线程将数据提交给接收线程处理时,驱动会将发送线程的优先级也赋予接收线程,使得数据即使跨了进程也能以同样优先级得到处理。不过如果发送线程优先级过低,接收线程将以预设的最小值运行。 该域的值来自于flat_binder_object中flags成员。 |
struct list_head async_todo |
异步交互等待队列;用于分流发往本节点的异步交互包 |
5.3.2 Binder 引用在驱动中的表述
和实体一样,Binder的引用也是驱动根据传输数据中的flat_binder_object创建的,隶属于获得该引用的进程,用struct binder_ref结构体表示:
成员 |
含义 |
int debug_id; |
调试用 |
struct rb_node rb_node_desc; |
每个进程有一棵红黑树,进程所有引用以引用号(即本结构的desc域)为索引添入该树中。本成员用做链接到该树的一个节点。 |
struct rb_node rb_node_node; |
每个进程又有一棵红黑树,进程所有引用以节点实体在驱动中的内存地址(即本结构的node域)为所引添入该树中。本成员用做链接到该树的一个节点。 |
struct hlist_node node_entry; |
该域将本引用做为节点链入所指向的Binder实体结构binder_node中的refs队列 |
struct binder_proc *proc; |
本引用所属的进程 |
struct binder_node *node; |
本引用所指向的节点(Binder实体) |
uint32_t desc; |
本结构的引用号 |
int strong; |
强引用计数 |
int weak; |
弱引用计数 |
struct binder_ref_death *death; |
应用程序向驱动发送BC_REQUEST_DEATH_NOTIFICATION或BC_CLEAR_DEATH_NOTIFICATION命令从而当Binder实体销毁时能够收到来自驱动的提醒。该域不为空表明用户订阅了对应实体销毁的‘噩耗’。 |
6 Binder 内存映射和接收缓存区管理
fd = open("/dev/binder", O_RDWR);
mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
有分配必然有释放。接收方在处理完数据包后,就要通知驱动释放data.buffer所指向的内存区。在介绍Binder协议时已经提到,这是由命令BC_FREE_BUFFER完成的。
7 Binder 接收线程管理
8 数据包接收队列与(线程)等待队列管理
9 总结
Binder使用Client-Server通信方式,安全性好,简单高效,再加上其面向对象的设计思想,独特的接收缓存管理和线程池管理方式,成为Android进程间通信的中流砥柱。
- 顶
- 31
- 踩
- 1
- 上一篇linux开发者的一天
我的同类文章
- •linux开发者的一天2010-11-12
- •大内核锁将何去何从2010-05-25
参考知识库
- 猜你在找
- 从零写Bootloader及移植uboot、linux内核、文件系统和驱动
- 从三星官方内核开始移植-uboot与系统移植第17部分
- 嵌入式Linux项目实战:三个大项目(数码相框、摄像头驱动和电源管理),九个衍生项目视频教程
- Android驱动深度开发视频教程
- “攒课”课题3:安卓编译与开发、Linux内核及驱动
- Android Bander设计与实现 - 设计篇
- Android Bander设计与实现 - 设计篇
- Android Bander设计与实现 - 设计篇
- Android Bander设计与实现 - 设计篇
- 转Android Bander设计与实现 - 设计篇
Android Bander设计与实现 - 设计篇相关推荐
- android Binder机制(一)架构设计
Binder 架构设计 Binder 被设计出来是解决 Android IPC(进程间通信) 问题的.Binder 将两个进程间交互的理解为 Client 向 Server 进行通信. 如下:bind ...
- Android应用程序和其设计思想--转载----做记录
转载一篇Android 的先关文章,无论什么时候看都觉得有收获 文章来源地址 http://www.open-open.com/lib/view/open1466070376316.html 以下是正 ...
- 本科毕业论文-软件开发类-《基于Android端开关控制系统的设计与实现》-论文模板
目 录 前言 一.任务书 二.目录 三.论文正文 摘要 ABSTRACT 1.引言 2.系统开发环境 2.1可行性分析 2.2 开发工具介绍 3.需求分析 3.1 功能需求分析 3.2 数据流程图 ...
- 移动端app设计开发经验之设计篇
分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow @我爱静电 在&l ...
- 基于Android微博整合客户端的设计与实现 毕业设计论文开题报告
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! < ...
- android媒体播放器课程设计,基于Android的多媒体播放器课程设计报告
基于Android的多媒体播放器课程设计报告 p/*/pp源代码. 我希望这篇文章对初学者有帮助. 希望更多的人在网络上共享自己的学习成果./pp*/pp1 .开发环境/ppAndroid是基于Lin ...
- 《基于Android微博整合客户端的设计与实现》毕业设计论文开题报告
<基于Android微博整合客户端的设计与实现>毕业设计论文开题报告 说 明 1.开题报告是保证毕业设计(论文)质量的一个重要环节,为规范毕业设计的开题报告,特印发此表. 2.学生应 ...
- Hbase基础(特点、架构、应用场景、集群搭建、HA设计)这一篇就够了
Hbase基础(特点.架构.应用场景.集群搭建.HA设计)这一篇就够了 1. Hbase特点 2. Hbase VS RDBMS 3. Hbase架构及版本选择 4. Hbase应用场景 5. Ntp ...
- android应用课程设计报告,基于Android的多媒体播放器课程设计报告.doc
基于Android的多媒体播放器课程设计报告.doc 基于Android的多媒体播放器课程设计报告2014-01-02 224652 转载标签 android多媒体播放器嵌入式课程设计报告it分类 我 ...
最新文章
- log4j.logger java_log4j的多logger记录日志的简明使用
- 【九度OJ】题目1206:字符串连接
- 前端要懂mysql_【灵魂拷问】你真的懂得Mysql的管理和使用吗?
- art.dialog弹出框后再根据其内部iframe的大小调整大小
- java 文件url地址_简单的解析文件,取URL地址,并根据地址抓下页面
- mysql用的sql标准_标准SQL语言的用法_MySQL
- linux C(hello world)三个数最大和三个数最新
- HTML页面用ajax方式传递表单数据给后台,数据库插入信息后将json对象传回前端JS处理(前后台交互)
- c语言 内存清除函数,C语言内存初始化函数MEMSET的用法
- 架构之美—需求审核直接影响设计成败(2)
- 【使用技巧】【图像编辑和处理】将多幅图片放到一块方便对比
- 小新pro13 (2020款,Nvidia MX350)+win10+cuda10.2+cudnn7.6+pytorch搭建深度学习环境
- 拾叶集 - 江湖一剑客
- springboot--入门程序实现CRUD操作
- Rosalind第88题:Counting Rooted Binary Trees
- CSS3知识点复习与总结
- html input 删除线,css样式实现字体删除线效果
- Swiper:无限循环滚动时出现空白页/页面内容不刷新
- 解决idea显示properties文件中文乱码
- android模拟器 报错:X Error of failed request: BadRequest (invalid request code or no such operation)
_FD?
目前我这边在分析AMS老是卡在waitForResponce上,最后一栈是ioctl,log中又不直观,也不知道什么原因。
不知道谁翻的谁的
最后一部分,读着不太顺。 不管怎样,让大家清晰了解了Binder。 功不可没 ~~
但是有一点必须说的,题目中的“binder”拼错了
http://www.cnblogs.com/albert1017/p/3849585.html
已完成的一部分,还在继续学习,欢迎大家指正。
楼主适合写书啊,理解的太透彻了!
精髓在于binder_ref和binder_node的讲解,简简单单几句话,点醒梦中人。
再读几遍
必读!
在网上搜索你的网名,最终找到了这里(之前是在其他的网站看到你的文章)。对你的辛勤劳动说句“感谢”!
大学毕业两年了,却没有感觉自己的技术实力得到很大的长进,也不知道什么时候能到达你的高度。向你学习!
你应该出个书,肯定比市面上的那些分析Android的书都好!
很多人只是分析代码本身,结果迷失在浩如烟海的代码中;很少人从设计者的角度出发,你做到了!
楼主的功力不是一般的深厚!
谢谢博主。
最顶层的目录是嵌入的,我看csdn的博客没有这个工具?
求教:为什么说除了socket,其它的IPC机制不支持Client-Server通信方式?比如使用管道不能实现C/S通信吗?我有点迷惑,C/S通信不就是两个进程间的通信吗,有什么特殊的呢?为什么说只有socket才支持。
我的邮箱:chjm8569@gmail.com。
谢谢
真的很感谢楼主的分享,也很佩服楼主的功底,加油~
结果在LZ这篇文章的指导下,我没花太多力气就读懂了Service Manager. 关于驱动完成Handler到指针的转换太重要了, -- 一开始我认为LZ开玩笑的,结果真的是这样。 -- 简单地说,如果想不读Binder驱动就明白Service Manager以及Binder的实质,LZ这篇文章毫无疑问是我第一要推荐的。非常感谢LZ,同时LZ深厚的技术功底必须要赞一个!
请问:
1.server在向servicemanager注册时,如何表示自己的特殊性? 以便client在向serivcemanager查询?
内容还不错,鼓励。
原文地址: http://blog.csdn.net/universus/article/details/6211589