Android Binder interprocess Communication---Registering service components---Sending and processing bc_reply return protocol

Source: Internet
Author: User

This article refers to "Android system source code scenario analysis", author Luo Shenyang

First, the test code:

~/android/external/binder/server

----FregServer.cpp

~/android/external/binder/common

----IFregService.cpp

----IFregService.h

~/android/external/binder/client

----FregClient.cpp


Binder Library (Libbinder) code:

~/android/frameworks/base/libs/binder

----BpBinder.cpp

----Parcel.cpp

----ProcessState.cpp

----Binder.cpp

----IInterface.cpp

----IPCThreadState.cpp

----IServiceManager.cpp

----Static.cpp

~/android/frameworks/base/include/binder

----Binder.h

----BpBinder.h

----IInterface.h

----IPCThreadState.h

----IServiceManager.h

----IBinder.h

----Parcel.h

----ProcessState.h


Drive Layer Code:

~/android//kernel/goldfish/drivers/staging/android

----BINDER.C

----Binder.h


Second, source code analysis

On Android Binder interprocess communication---Registering Service components---client sends bc_transactionhttp://blog.csdn.net/jltxgcy/article/details/ 260,761,491 in the last thread, sleep to wait for interprocess communication results.

In the http://blog.csdn.net/jltxgcy/article/details/26076149 article, We assume that thread threads that request a service component Fregservice are waiting for service Manager to complete the registration operation in the binder driver function Binder_thread_read. Now that Service Manager has completed the registration of the service component Fregservice, and thread threads have been awakened by the binder driver, then it executes the function Binder_thread_ Read to process the work item in its TODO queue.

There is now a work item of type Binder_work_transaction in the TODO queue that requests a thread that registers the service component Fregservice, so next we analyze the function Binder_thread_ Read the process of processing this work item.

~/android//kernel/goldfish/drivers/staging/android

----BINDER.C

Static Intbinder_thread_read (struct Binder_proc *proc, struct binder_thread *thread,void __user *buffer, int size, signed        Long *consumed, int non_block) {void __user *ptr = buffer + *consumed;void __user *end = buffer + size; ... while (1) {uint32_t cmd;struct binder_transaction_data tr;struct binder_work *w;struct binder_transaction *t = N Ull;if (!list_empty (&thread->todo)) W = list_first_entry (&thread->todo, struct binder_work, entry);// Remove this work item of type binder_work_transaction from the TODO queue of thread threads else if (!list_empty (&proc->todo) && wait_for_ proc_work) W = list_first_entry (&proc->todo, struct binder_work, entry); else {...} ... switch (w->type) {case binder_work_transaction: {t = container_of (w, struct binder_transaction, work);// The host binder_transaction structure of the work item is then retrieved and saved in the variable T} break;........if (T->buffer->target_node) {//null ...} else {tr.target.ptr = Null;tr.cookie = Null;cmd = br_reply;} Tr.code = T->code;//0tr.flags = T->fLags;//0tr.sender_euid = T->sender_euid;if (t->from) {struct Task_struct *sender = t->from->proc->tsk; Tr.sender_pid = Task_tgid_nr_ns (sender, Current->nsproxy->pid_ns);} else {tr.sender_pid = 0;} tr.data_size = t->buffer->data_size;//data buffer size tr.offsets_size = t->buffer->offsets_size;// Offset array size tr.data.ptr.buffer = (void *) T->buffer->data + proc->user_buffer_offset;//kernel buffer The kernel space address and user space address differ by a fixed value and is saved in its member variable User_buffer_offset tr.data.ptr.offsets = Tr.data.ptr.buffer + ALIGN (t->buffer->data_size, sizeof ( void *));//offset is saved in the back of the data buffer if (Put_user (cmd, (uint32_t __user *) ptr))//Returns the command return-efault;ptr + = sizeof (uint32_t); Copy_to_user (PTR, &tr, sizeof (TR)))//Will BINDER_TRANSACTION_DATA structure TR return return-efault;ptr + = sizeof (TR); list _del (&t->work.entry);//delete the task item T->buffer->allow_user_free = 1;//Allow release if (cmd = = Br_transaction &&! T->flags & Tf_one_way)) {...} else {t->buffer->transaction = Null;kfree (t);//Release Binder_Transaction structural Body t ....} break;} Done:*consumed = The sum of the size of the Ptr-buffer;//cmd and Binder_transaction_data structure tr .... return 0;}
First, the work item of type binder_work_transaction is removed from the todo queue of thread threads and stored in the variable W. The host binder_transaction structure of the work item is then retrieved and saved in the variable T.

The binder_transaction_data result body TR is then initialized with the binder_transaction structure T. The cmdbr_reply and TR are then returned to the user space.

After thread threads executes the completion function Binder_thread_read, it returns to the function Binder_ioctl and returns to the member function Talkwithdriver of the Ipcthreadstate class. Finally, return to the member function waitForResponse of the Ipcthreadstate class to process the br_reply return protocol, as follows:

~/android/frameworks/base/libs/binder

----IPCThreadState.cpp

status_t Ipcthreadstate::waitforresponse (Parcel *reply, status_t *acquireresult) {int32_t cmd;    int32_t err;        while (1) {if ((Err=talkwithdriver ()) < no_error) break;  .... cmd = Min.readint32 ();//cmd for br_reply .... switch (cmd) {...... case                Br_reply: {binder_transaction_data tr;                Err = Min.read (&tr, sizeof (TR));//read from the contents of the protocol buffer mIn to a binder_transaction_data struct tr ... if (reply) {//NOT NULL if ((Tr.flags & tf_status_code) = = 0) {//tr.flags is 0 r Eply->ipcsetdatareference (//) The results of inter-process communication saved in the binder_transaction structure tr are saved in the Parcel object reply Reinterpre T_cast<const uint8_t*> (Tr.data.ptr.buffer), Tr.data_size, Rein  Terpret_cast<const size_t*> (tr.data.ptr.offsets), tr.offsets_size/sizeof (size_t),                          FreeBuffer, this);                } else {...}            } else {...}           } goto finish;    .........        } }finish: ... return err;}
First read a br_reply return protocol code from the return protocol buffer min. The contents of the protocol buffer min are then read into a binder_transaction_data structure tr.
If the member variable of the binder_transaction_data struct TR, the tf_status_code bit of flags, equals 0, it indicates that an inter-process communication request made prior to the current process has been successfully processed. Therefore, the results of inter-process communication saved in the binder_transaction structure tr are saved in the Parcel object reply, which is achieved by invoking the reply of the member functions of the Parcel object ipcsetdatareference. The implementation is as follows:

~/android/frameworks/base/libs/binder

----Parcel.cpp

void Parcel::ipcsetdatareference (const uint8_t* data, size_t datasize,    const size_t* objects, size_t objectscount, Release_func Relfunc, void* relcookie) {    freedatanoinit ();    Merror = No_error;    Mdata = const_cast<uint8_t*> (data);//Buffer mdatasize = mdatacapacity = DataSize for inter-process communication result data,    buffer size for interprocess communication result data    ..........    Mdatapos = 0;    ..........    Mobjects = Const_cast<size_t*> (objects);//offset array start position    mobjectssize = mobjectscapacity = objectscount;//offset array size    .........    Mowner = relfunc;//freebuffer    Mownercookie = relcookie;//Current Thread Ipcthreadstate object ...    }
The parameter data points to the buffer used to hold the inter-process communication result data, and its size is described by the parameter datasize. The argument object points to a Binder object offset array that describes the location of the binder object held in the inter-process communication data buffer, whose size is described by the parameter objectscount, and the parameter relfunc is a function pointer. It points to the member function FreeBuffer of the Ipctheadstate class, and the parameter Relcookie points to the Ipcthreadstate object of the current thread.

Then assign to the parcel class of the different member variables, Mdata is the data buffer of the real address, mdatasize for the data buffer size, Mdatapos for the next to read in the location. Mobjects is the offset array start address, mobjetctsize is the offset array mobjects the next location to read the data, mobjectscapacity is the size of the offset array.

Mowner holds the FreeBuffer function pointer, mownercookie the current thread of the depositary Ipcthreadstate object. After the thread obtains the interprocess communication result data that is saved in the current parcel object, it will refactor the parcel object, and when the parcel object is being refactored, Calls its member variables Mowner and Mownercookie to invoke the member function of the Ipctheadstate class FreeBuffer frees the data buffer Mdata it uses internally. Since this data buffer is allocated in the binder driver, that is, it points to a kernel buffer, the member function FreeBuffer of the Ipcthreadstate class is passed Bc_free_ The buffer command protocol notifies the binder driver to release the kernel buffer.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.