您的位置:首页 > 移动开发 > Android开发

Android Binder相关的一些基础知识点.

2016-12-03 10:49 531 查看
    文章仅仅用于个人的学习记录,基本上内容都是网上各个大神的杰作,此处摘录过来以自己的理解学习方式记录一下。    个人最为认可和推崇的大神文章:          http://blog.csdn.net/luoshengyang/article/details/6618363     罗升阳Binder系列文章          http://blog.csdn.net/innost/article/details/47208049                Innost的Binder讲解          https://my.oschina.net/youranhongcha/blog/149575              侯 亮的Binder系列文章.1、模板类         在IInterface.h文件中有几个非常重要的模板类.         BnInterface,它和BpInterface相对应都算是binder的业务层的动西(内部封装了通信方面的只是),注意使用的时候如BnInterface<ISer         vice>。注意此时如class A : public BnInterface<IService> 这个时候类A是继承了 BnInterface、Iservice、BBinder三个类。
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface>  queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
 
protected:
virtual IBinder*onAsBinder();
};
          BpInterface:使用方法和BnInterfface同理。当class B : public BpInterface <IServiceManager> 此时通过这个模板类,类B继承了          BpInterface、IServiceManager、BpRefBase三个类,一定要注意这个BpRefBase.(里面有mRemote,它就是BpBinder)
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
 
protected:
virtual IBinder*onAsBinder();
};
         interface_cast:注意这个模板类,它其实不是一种类型强制转换它里面是有代码的。         当使用的时候interface_cast<IServiceManager>(mBinder)的时候,就是调用模板参数也就是<>里面的类的asInterface(mBinder)        并且把后面的小括号里面的参数传入进去。至于这个类的asInterface的实现,其实标准也是用的宏定义。
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
2、宏定义。      这个两个宏定义说白了就是方便了一些开发,因为这些都是使用Binder时候标准,都一个类型,所以做成了这样。也是在IInterface.h当中     a、 声明接口DECLARE_META_INTERFACE(INTERFACE),注意它就是在.h文件中进行的定义一句话调用即可。如:      DECLARE_META_INTERFACE(ServiceManager);//注意一都3是不带前缀I的.注意这种宏定义的形式最后面有一个斜杠"\"
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor;\
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj);\
virtual const android::String16& getInterfaceDescriptor() const;  \
I##INTERFACE();   \
virtual ~I##INTERFACE();  \
       b、实现接口口IMPLEMENT_META_INTERFACE(INTERFACE, NAME) .有声明就有实现嘛,基本的调用方式:       IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager") ;实现处传入的第一个参数和声明处一样,第二各参       数一个字符串名字,代表这个binder的描述。
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)   \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16&\
I##INTERFACE::getInterfaceDescriptor() const {  \
return I##INTERFACE::descriptor;\
}   \
android::sp<I##INTERFACE> I##INTERFACE::asInterface(\
const android::sp<android::IBinder>& obj)   \
{   \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) {  \
intr = static_cast<I##INTERFACE*>(  \
obj->queryLocalInterface(   \
I##INTERFACE::descriptor).get());   \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj);  \
}   \
}   \
return intr;\
}   \
I##INTERFACE::I##INTERFACE() { }\
I##INTERFACE::~I##INTERFACE() { }   \
           其中最重要的方法就是asInterface的实现了,把调用宏的地方传入的类全部替代INTERFACE。这个类当asInterface传入的参数是一个     BpBinder对象的时候,由于>queryLocalInterface返回null,所以会实例化BPXXXXXX(obj) 类这个XXXXX就是生命和实现处传入的类obj     就是调用asInterface传入的参数。在IInterface.h这个文件中的宏定义的下面就有这个asInterface的实现,通过参数description判断返回th     is还是null。asInterface的实现了BpBinder打包成BpInterface(一般是它的具体子类)           宏定义中的meta: 元 可以理解为最小单位什么的把,它把这个操作当成一个原子性的操作.           3、小知识点。     status_t 结构体错误表示,err == -EINTR err = -EBADF这几个值。     设备文件:/dev/binder . 驱动的设备文件具体用途有哪些那?            这个设备文件专门用于完成进程间通信而设置的一个虚拟设备文件,你应用程序想和内核的Binder驱动程序打交道,怎么打交道?      又不能直接访问,此时就通过这个设备文件,打开以后获得fd,然后用fd 返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收      数据。这样应用程序许就和驱动通过这个设备文件开始打交道。binder是内核中的一个字符驱动设备位于/dev/binder。客户端的服务代理      用来通过它向服务器(server)发送请求,服务器也是通过它把处理结果返回给客户端的服务代理对象。            Linux 中的设备有2种类型:字符设备(无缓冲且只能顺序存取)、块设备(有缓冲且可以随机存取)。每个字符设备和块设备都必须有主、     次设备号,主设备号相同的设备是同类设备(使用同一个驱动程序)。这些设备中,有些设备是对实际存在的物理硬件的抽象,而有些设备则是     内核自身提供的功能(不依赖于特定的物理硬件,又称为"虚拟设备")。每个设备在 /dev 目录下都有一个对应的文件(节点)         Linux将外设看作一个文件来管理, 用户使用外设就像使用普通文件一样。应用程序通过open, read, write等命令完成对设备的访问,可     以通过两种方法建立设备节点,一种是自己手动用mknod,另一种是存在udev,它会自动创建相应的设备节点。        4、Binder相关的几个路径      a、service manager Binder的上下文管理者这个native的程序的代码相关路径。service.exe            由于Server进程可能生死无常。如果让每个Client都去检测,压力实在太大。有了统一的管理机构Client只需要查询ServiceManager,            就能把握动向,得到最新信息。            android\frameworks\native\cmds\servicemanager            里面有service manager程序的主文件:service_manager.c,还有Binder.c、Binder.h等来封装service manager的一些binder操作      b、这一层其实算是封装(驱动正真操作)函数,供类似JNI层等调用。它算是库函数.           声明:android\frameworks\native\include\binder           实现:android\frameworks\native\libs\binder.cpp           里面有:Binder、BpBinder、IIterface、Ibinder、IPCThreadState、ProcessState等等主要的几个功能类的声明和实现。     c、一些Android Linux驱动层对Binder driver 的实现如:结构体的声明了,函数的调用了。           android\external\kernel-headers\original\uapi\linux           里面有binder.h头文件,声明了如:struct binder_transaction_data、 eum transaction_flags、binder_driver驱动的一些协议和命令           码的标识 等等          d、Linux内核的一些公共的东西:           android\system\core\include\utils           android\system\core\libutils\           如Thread.cpp等等.     f、binder的驱动代码: 十分的重要!!!         android/kernel/drivers/android/ binder.c         里面定义了一些binder机制所需的结构体如:binder_node、binder_proc、binder_ref等等。还创建了 /dev/binder的设备文件。5、一些基础的认知。     a、 ProcessState类每个进程一个,它被设计成全局单例模式。ProcessState是在进程内全局唯一的,进程在它就会在没有必要delete.            由于ProcessState的惟一性,因此一个进程只打开设备一次。     b、IPCThreadState类,这个类最终和binder驱动打交道,它是线程单例的,每个线程一个IPCThreadState。每个IPCThreadState中都有         一个Parcel mIn、一个Parcel  mOut,其中mIn是用来接收来自Binder设备的数据的,而mOut则是用来存储发往Binder设备的数据的。     c、asInterface的设计,通过对比java层和底层的这个方法的实现,发现大体的设计思路都一样,首先都是由IBinder类来定义,所以无论          Binder的代理:BpBinder(native层)、BinderProxy(java层),还是Binder实现 : BBinder、Binder.  都需要实现这个方法。而当          asInterface传入的是代理的时候(此时一般是跨进程调用),会返回代理对象,而当传入的是Binder实体的时候(此时一般是本地调          用)会返回this。这个返回值是由于,它们分别对queryLocalInterface()函数的不同实现导致的,引用代理端会返回null,而实体端会          返回this。     d、Binder整个构造的一个小的认知。           Binder的构架其实可以分为业务层和通信层。           所谓通信层,就是最终和Bidner driver交互的地方。是通过BBinder和BpBinder来实现。           业务层就是上面那些BNServiceXXXX 、BpServiceXXXX等等这些处理操作逻辑的。它们被google工程师巧妙的把通信层用的同喜融于           其中,各司其职。        6、binder机制的处理模型。     binder机制在android系统的进程间通讯模型总结如下:    (1)客户端通过某种方式得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。它可以像其他本地对象一样         调用其方法,访问其变量。    (2)客户端通过调用代理对象的方法向服务器端发送请求信息。    (3)代理对象通过binder设备节点(/dev/binder),把用户请求信息发送到Linux内核空间(实际上是内存共享),由Binder驱动获取并发送到        服务进程。    (4)服务进程处理用户请求,并通过Linux内核的Binder驱动(驱动通过binder设备节点)返回处理结果给客户端的代理对象。    (5)客户端收到服务端的返回结果。    总结: 整个过程大致如上所述,可以想象一下binder机制的引入,给进程间的通讯带来什么好处?没错,就是“线程迁移”,就像是一个线                 程带着参数,进入另一个进程执行,然后带着结果返回,和调用自己的函数一样的效果。7、Android中Binder的数据拷贝           应用程序许通过系统调用mmap,调用到Binder驱动程序的binder_mmap函数。在此函数中会同时使用用户进程虚拟地址空间和内核虚     拟地址空间来映射同一个物理页面. 注意:内核的虚拟地址是所有进程共享的。          举个例子如,Client要将一块内存数据传递给Server,一般的做法是,Client将这块数据从它的进程空间拷贝到内核空间中,然后内核再        将这个数据从内核空间拷贝到Server的进程空间,这样,Server就可以访问这个数据了。但是在这种方法中,执行了两次内存拷贝操作,而      采用我们上面提到的方法,只需要把Client进程空间的数据拷贝一次到内核空间,然后Server与内核共享这个数据就可以了,整个过程只需     要执行一次内存拷贝,提高了效率。          整个数据流程大概如下:          1. Client将数据从用户空间传输到Binder驱动;(通过设备文件/dev/binder)          2. Binder驱动将第1步得到的数据拷贝到Service通过mmap申请得到的那块物理空间;(看出来service需要打开binder设备,申请空间)          3. Binder驱动将第2步得到的物理空间对应的虚拟地址传递给Service的用户空间;          4. Service的用户空间通过Binder驱动传递过来的虚拟地址来访问Client传输过来的数据。              整个过程只有第2步是需要拷贝数据的,这也是Binder进程间通信机制的精华所在。8、对一些系统调用的理解。      如在service_manager的进程中调用如:open、mmap、ioclt等。它们会只想到binder驱动中的对应的如:binder_open、binder_mmap     等函数当中。            这是有Linux的文件系统的设计决定的。Binder驱动程序和一般的驱动程序一样标注的注册实现一些东西。所以在用户空间,按照标准的    调用最终经过文件系统层到达驱动层,而驱动程序在初始化时会注册相关的接口到驱动层,从而上层的系统调用可以调用到它们注册的函数里     面去.9、内存共享和进程通信的小区别。           内存共享和进程间通信虽然讲的都是两个进程之间的事情,但是它们是有区别的,进程间通信有信息同步的意思,而共享内存在两个进程间     的信息是不同步的,即一个进程改变了共享内存的内容,但是另外一个进程是不知道的,它一般要配合一种进程间通信机制来告诉对方,共     享内存的内容发生改变了。  而老大所说的那种往文件里面存东西,感觉应该就是内存共享。另外一方需要监听这个文件的变化。10、常见的结构体。      struct flat_binder_object : 用来表示用户空间和内核空间传递的binder实体对象。      struct binder_node: 内核空间用来描述Binder对象的状态的,它是在驱动实现处binder.c声明的。      binder_transaction_data:代表一次通信事物,(就是这次通信的总过程)在用户空间和内核空间都有binder_transaction_data结构体,                                                  它们的结构都是一样的,当调用从用户空间调用writeTransactionData函数进入到内核空间的                                                  binder_transaction函数的时候,就会从用户空间的binder_transaction_data结构体缓冲区数据拷贝到空核空                                                  间的binder_transaction_data结构体缓冲区去.      struct binder_proc :代表一个Binder处理的进程。它与用户空间的ProcessState相对应。(一个进程一个)
struct binder_proc
{
struct hlist_node proc_node;
struct rb_root threads;
//在一个进程中,有多少“被其他进程进行跨进程调用的”binder实体,就会在该进程对应的nodes树中
生成多少个红黑树节点
struct rb_root nodes;
//一个进程要访问多少其它进程的binder实体,则必须在其refs_by_desc树中拥有对应的引用节点
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
int pid;
. . . . . .
. . . . . .
};
               这4棵树的节点类型是不同的   threads树的节点类型为binder_thread,nodes树的节点类型为binder_node,refs_by_desc树和        refs_by_node树的 节点类型相同,为binder_ref。这些节点内部都会包含rb_node子结构,该结构专门负责连接节点的工作,和前文的        hlist_node有点儿异曲同工,这 也是linux上一个常用的小技巧.11、两个获取servicemanager的函数。       在native层:               defaultServiceManager(),获得的是Service Manager的代理对象,用来访问Service Manager。得到代理以后就可以服务端去:        addservice,客户端:getservice等等的操作.  (客户端调用时)最终是BpServiceManager(new BpBinder(0))
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
//最终就是:gDefaultServiceManager = new BpServiceManager(new BpBinder(0)); 
gDefaultServiceManager = interface_cast<IServiceManager>( 
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
          在java层:                 getIserviceManager():(客户端调用时)最终获的ServiceManagerProxy(new BinderProxy)对象.传入的这个BinderProxy对应到          了native层的BpBinder(0).
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// sServiceManager = new ServiceManagerProxy(new BinderProxy()); 
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
12、servie作为binder实体的处理。           Server通过getService获得了Service Manager远程接口之后,通过addService把自己的Service添加到Service Manager中去,然后把       自己启动起来(joinInThread?),等待Client的请求.           而当service端的IPCThreadState接收到了Client处的请求后,就会调用BBinder类的transact函数(这就是着手处理客户端的请求的起始       点),并传入相关参数。BBinder的transact函数仅仅是调用了自己的(或者说子类重写的时候调用的子类的)onTransact函数。开始真正        的处理client的请求。            Binder服务端都需要loop等待Binder的请求      13、写一个工程的时候main函数的启动。       fork + exec两个系统调用就可以让你的程序的main函数跑起来。只不过编译器把这个两个帮忙调用了。14、C/C++语言中的sp              smart pointer还是strong pointer呢?留着后面有机会分析。就把它当做一个普通的指针看待,即sp<IServiceManager>就等价于           IServiceManager* 中括号中这个类的指针对象。sp是google搞出来的为了方便C/C++程序员管理指针的分配和释放的一套方法,类似       java的什么WeakReference之类的。以后的分析中,sp<XXX>就看成是XXX*就可以了.15、类似于handle的命名和作用            在windows的应该比较熟悉这个名字,这是对资源的一种标示,其实说白了就是某个数据结构,保存在数组中,然后handle是它在这个       数组中的索引。--->就是这么一个玩意儿。16、底层service manager处理一个如client端如addService的请求的时候。           总的来说:BpServiceManager发送了一个addService命令到BnServiceManager,然后收到回复。步骤:        IserviceMnager.transact--->BpBinder.transact--->IPCThreadState.tranSact..然后talkwithdriver,然后waitforresponse就可以.。17、一个完整的native层的实现      int main()     {         //getMediaPlayerService();直接调用这个函数能获得BpMediaPlayerService吗?不能,为什么?因为我还没打开binder驱动呐!但是你         //在java应用程序里边却有google已经替你封装好了。         //所以,纯native层的代码,必须也得像下面这样处理:        sp<ProcessState> proc(ProcessState::self());//这个其实不是必须的,因为好多地方都需要这个,所以自动也会创建.        getMediaPlayerService();        //还得起消息循环呐,否则如果Bn那边有消息通知你,你怎么接受得到呢?       ProcessState::self()->startThreadPool();       //至于主线程是否也需要调用消息循环,就看个人而定了。不过一般是等着接收其他来源的消息,例如socket发来的命令,然后控制      //MediaPlayerService就可以了。}18、Binder中的命令码       1)、 应用程序向binder设备发送消息的消息码一半都是以BC_XXXX  BC开头的,       2)、 binder设备向应用程序回复消息的消息码以BR_XXXXX开头       消息码的定义在binder_module.h中, 请求消息码和回应消息码的对应关系,需要查看Binder驱动的实现才能将其理清楚。19、一些定义规范     Android要求所有的Binder不管是代理方还是实体方都必须实现IBinder接口,而IBinder又会实现IInterface接口。20、binder通信的一些特点。        1)、binder本身是IPC机制,它的主要作用是跨进程通信和调用,而不是传递数据。用它来传递较大的数据是不合适的,               会溢出的。可以考虑使用Content provider、共享内存等机制。        2)、在跨进程通信时,传递指针值是没什么意义的。传来传去的都是parcel。两端必须自己解释parcel。21、传输时候的一次操作的理解          Binder IPC机制的大体思路:它将每次“传输并执行特定语义的”工作理解为一个小事务,既然所传输的数据binder_transaction_data          类型的,那么这种事务的类名可以相应地定为binder_transaction。系统中当然会有很多事务啦,那么发向同一个进程或线程的若干事务就      必须串行化起来,因此binder驱动为进程节点(binder_proc)和线程节点(binder_thread)都设计了个todo队列。todo队列的职责就     是“串行化地组织待处理的事务”,这样看来,传输动作的基本目标就很明确了,就是想办法把发起端的一个binder_transaction节点,插     入到目标端进程或其合适子线程的todo队列去。22、IPCThreadState执行一次通信操作的基本流程。        IPCThreadState::transact()会考虑本次发起的事务是否需要回复。“不需要等待回复的”事务,在其  flag标志中会含有TF_ONE_WAY,表    示一去不回头。而“需要等待回复的”,则需要在传递时提供记录回复信息的Parcel对象,一般发起transact()的用户会提供这个Parcel对象,    如果不提供,transact()函数内部会临时构造一个假的Parcel对象。最后在waitForResponse()中是通过调用talkWithDriver()来和binder驱动    打交道的,说到底会调用ioctl()函数。因为ioctl()函数在传递BINDER_WRITE_READ语义时,既会使用".输入buffer"也会使用"输出buffer",     所以IPCThreadState专门搞了两个Parcel类型的成员变量:mIn和mOut。总之就是,mOut中的内容发出去,发送后的回复写进mIn。23、整体构架图和所处空间。(罗老师的图)           从上图可以看出来:client、server以及service manager 都是位于用户进空间.而binder的驱动为与内核空间。并且binder驱动提供设备文    件/dev/binder来让用户空间的组件通过open和ioctl文件操作函数与Binder驱动程序进行通信.也可以看出Client和Server之间的进程间通信通    过Binder驱动程序间接实现.24、Binder设备文件的建立.            此处的/dev/bider设备文件属于:(misc device)杂项设备,是在嵌入式系统中用得比较多的一种设备驱动。其实是因为这些字符设备不符合      预先确定的字符设备范畴,所有这些设备采用主编号10 ,一起归于misc device,其实misc_register就是用主标号10调用register_chrdev()的。     算是一种字符设备(char device).           在android/kernel/drivers/android/ binder.c的驱动文件中.初始化的时候
static int __init binder_init(void)
{
int ret;
 
binder_deferred_workqueue = create_singlethread_workqueue("binder");
if (!binder_deferred_workqueue)
return -ENOMEM;
 
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
if (binder_debugfs_dir_entry_root)
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
binder_debugfs_dir_entry_root);
ret = misc_register(&binder_miscdev); //misc_register这个函数创健设备文件。
if (binder_debugfs_dir_entry_root) {  // 其余的逻辑主要是在/proc目录创建各种Binder相关的文件,供用户访问
debugfs_create_file("state",
				S_IRUGO,
				binder_debugfs_dir_entry_root,
				NULL,
				&binder_state_fops);
debugfs_create_file("stats",
				S_IRUGO,
				binder_debugfs_dir_entry_root,
				NULL,
				&binder_stats_fops);
debugfs_create_file("transactions",
				S_IRUGO,
				binder_debugfs_dir_entry_root,
				NULL,
				&binder_transactions_fops);
debugfs_create_file("transaction_log",
				S_IRUGO,
				binder_debugfs_dir_entry_root,
				&binder_transaction_log,
				&binder_transaction_log_fops);
debugfs_create_file("failed_transaction_log",
				S_IRUGO,
				binder_debugfs_dir_entry_root,
				&binder_transaction_log_failed,
				&binder_transaction_log_fops);
}
return ret;
}
            通过ret = misc_register(&binder_miscdev)来创建设备文件.然后有:
static const struct file_operations binder_fops = { //设备文件的操作方法binder_fops可以看出,
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl, //icto函数会对应到这里。
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap, // 设备文件的mmap ,对应到驱动的binder_mmap
.open = binder_open, // 外面调用该设备打开设备文件,会走到驱动的binder_open.
.flush = binder_flush,
.release = binder_release,
};
static struct miscdevice binder_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "binder",
.fops = &binder_fops
};
             通过binder_miscdev结构体和函数配合,在binder_fops定义了驱动和系统调用的转换。25、binder继承关系图:       java层:       native层如下:      26、调用service manager 的addService函数把自己注册到service manager当中的理解    最起码放到struct svcinfo 这个链表当中.27、BpBinder找对应的Binder实体的大体过程.      如进程1的BpBinder在发起跨进程调用时,向binder驱动传入了自己记录的句柄值,(注意此时BpBinder(handle)已经准确获得)binder驱   动就会在"进程1对应的binder_proc结构"的引用树中查找和句柄值相符的binder_ref节点,一旦找到binder_ref节点,就可以通过该节点的   node域找到对应的binder_node节点,这个目标binder_node当然是从属于进程2的binder_proc啦,不过不要紧,因为binder_ref和   binder_node都处于binder驱动的地址空间中,所以是可以用指针直接指向的。目标binder_node节点的cookie域,记录的其实是进程2中   BBinder的地址,binder驱动只需把这个值反映给应用层,应用层就可以直接拿到BBinder了。(拿到的其实就是地址.)28、开启线程池相关的问题。       到底有多少个线程在为Service服务呢?目前看来是两个:            主线程也调用joinThreadPool读取Binder设备,查看是否有请求。看来,binder设备是支持多线程操作的,其中一定是做了同步方面的      工作. Binder驱动程序要求进程创建一个新的线程时,它就会把requested_threads值加1,这时候新的线程需要使用bc_register_loop命令       来通知Binder驱动程序它创建好了;如果这个线程不是Binder驱动程序要求创建的,那就要用bc_enter_looper命令来注册到Binder驱动程       序中去了。           每个binder线程都会通过设备文件/dev/binder来和binder驱动交互。有两种类型的binder进程间通信请求,一种是分配给指定的binder线       程的,一种是分配给进程本身的。binder线程通过一个while循环来不断进入binder驱动去轮循自己是否有新的binder进程间通信请求需要      处理。轮循的规则是先检查有没有指定分配给它的。有的话,就先处理,否则的话,再去检查它所属进程是否有新的binder进程间通信请     求需要处理。同样,有的话就去处理,没有的话,就进入睡眠等待状态。等到有新的binder进程间通信请求需要处理它或者它所属进程来     处理时,binder线程就会被唤醒。至于是哪个binder线程先被唤醒,就跟内核的调度有些相关了。不过这不是重点,因为处理睡眠状态的     binder线程都是属于空闲的,分配给谁来处理都是一样。29、Binder中所有组件的整体描述        在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和    Service  Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件    便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施   上,进行Client-Server之间的通信。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息