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

    xiaoxiao2021-12-14  15

    文章仅仅用于个人的学习记录,基本上内容都是网上各个大神的杰作,此处摘录过来以自己的理解学习方式记录一下。     个人最为认可和推崇的大神文章:            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          v ic e>。注意此时如class A : public  BnInterface<ISer v ic e>  这个时候类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之间的通信。
    转载请注明原文地址: https://ju.6miu.com/read-968676.html

    最新回复(0)