Article reprinted to CSDN community Luo Shenyang's Android tour, original address: http://blog.csdn.net/luoshengyang/article/details/6666491
In the previous article on the Android system anonymous shared memory Ashmem (Anonymous shared Memories) driver Source code Analysis, we systematically introduced the implementation principle of anonymous shared memory of Android system, It focuses on how it assists the memory management system to effectively manage memory, and in the previous article on the Android system anonymous shared memory Ashmem (Anonymous shared Memories) Brief introduction and Learning Plan, we also mentioned that Another feature of anonymous shared memory on Android is the process of sharing between processes through the binder interprocess communication mechanism, in this article, we will describe in detail how the anonymous shared memory of the Android system uses the binder interprocess communication mechanism for inter-process sharing.
Since the principle of inter-process sharing within an anonymous share of the Android system involves the knowledge of the binder interprocess communication mechanism, it is desirable to have a good understanding of the binder interprocess communication mechanism of the Android system before continuing to read this article. Specifically refer to the Android interprocess communication (IPC) mechanism binder for a brief introduction and learning plan for this article.
On the Android system anonymous shared memory Ashmem (Anonymous shared Memories) Brief introduction and Learning Plan in this article, we give an example to briefly describe the anonymous shared memory mechanism of the Android system and how to use it, in this article, We continue to use this example to illustrate how the anonymous shared memory of the Android system uses the binder interprocess communication mechanism for inter-process sharing. To facilitate the description, combining the knowledge of the previous binder interprocess communication mechanism, we use the following sequence diagram to summarize the process of transferring the file descriptor of the anonymous shared memory file in this instance between processes:
What we need to focus on here is the dashed box section, which implements the method of sharing the same open file in two processes in the binder driver. We know that in a Linux system, a file descriptor is actually an integer. Each process has an array of open files in the kernel space, the integer value of this file descriptor is used to index the array, and the file descriptor is only valid within this process, that is, in different processes, the same file descriptor value, which may represent different open files. Therefore, when transferring file descriptors between processes, it is not possible to briefly pass a file descriptor from one process to another, which must be transformed so that the file description is valid in the target process, and it is consistent with the open file corresponding to the file descriptor of the source process, so that it can be shared.
In the article on Service Manager becoming the Binder daemon of the Android interprocess communication (IPC) mechanism, we introduce the data structure of the binder object used to transfer the struct flat_binder_object, It is defined in the Kernel/common/drivers/staging/android/binder.h file:
[CPP]View Plaincopy
- /*
- * This is the flattened representation of a Binder object for transfer
- * Between processes. The ' offsets ' supplied as part of a binder transaction
- * contains offsets into the data where these structures occur. The Binder
- * Driver takes care of re-writing the structure type and data as it moves
- * Between processes.
- */
- struct Flat_binder_object {
- / * 8 bytes for large_flat_header. * /
- unsigned long type;
- unsigned long flags;
- / * 8 bytes of data. * /
- Union {
- void *binder; / * Local Object * /
- signed long handle; / * Remote Object * /
- };
- / * Extra data associated with local object * /
- void *cookie;
- };
The field type is an enumeration type, and its value range is:
[CPP]View Plaincopy
- enum {
- Binder_type_binder = B_pack_chars (' s ', ' B ', ' * ', b_type_large),
- Binder_type_weak_binder = B_pack_chars (' W ', ' B ', ' * ', b_type_large),
- Binder_type_handle = B_pack_chars (' s ', ' h ', ' * ', b_type_large),
- Binder_type_weak_handle = B_pack_chars (' W ', ' h ', ' * ', b_type_large),
- BINDER_TYPE_FD = B_pack_chars (' f ', ' d ', ' * ', b_type_large),
- };
The TYPE of binder object We are going to introduce here is BINDER_TYPE_FD, and the value of the file descriptor to be transferred is saved in the handle domain.
The server startup process in the process communication (IPC) mechanism binder in the Android system source code analysis in this article, we detail the binder object in the process of communication transmission between the complete process, here is no longer detailed, interested in reading can go back to reference. Here, we focus only on the related processing logic of the binder object of the file descriptor type in the binder driver.
The binder object of the file descriptor type is implemented in the binder driver's related processing logic in the Binder_transact function, which is defined in the Kernel/common/drivers/staging/android/ In the Binder.c file:
[CPP]View Plaincopy
- static void
- Binder_transaction (struct binder_proc *proc, struct binder_thread *thread,
- struct Binder_transaction_data *tr, int reply)
- {
- struct binder_transaction *t;
- struct binder_work *tcomplete;
- size_t *OFFP, *off_end;
- struct Binder_proc *target_proc;
- struct Binder_thread *target_thread = NULL;
- struct Binder_node *target_node = NULL;
- struct List_head *target_list;
- wait_queue_head_t *target_wait;
- struct Binder_transaction *in_reply_to = NULL;
- struct Binder_transaction_log_entry *e;
- uint32_t Return_error;
- ......
- OFFP = (size_t *) (T->buffer->data + ALIGN (tr->data_size, sizeof (void *)));
- ......
- Off_end = (void *) OFFP + tr->offsets_size;
- For (; OFFP < off_end; offp++) {
- struct Flat_binder_object *fp;
- ......
- fp = (struct flat_binder_object *) (T->buffer->data + *OFFP);
- switch (fp->type) {
- ......
- Case binder_type_fd: {
- int target_fd;
- struct file *file;
- if (reply) {
- if (! ( In_reply_to->flags & Tf_accept_fds)) {
- Binder_user_error ("Binder:%d:%d got reply with FD,%LD, but Target does isn't allow fds\n",
- Proc->pid, thread->pid, Fp->handle);
- Return_error = br_failed_reply;
- Goto err_fd_not_allowed;
- }
- } Else if (!target_node->accept_fds) {
- Binder_user_error ("Binder:%d:%d got transaction with FD,%LD, but Target does isn't allow fds\n",
- Proc->pid, thread->pid, Fp->handle);
- Return_error = br_failed_reply;
- Goto err_fd_not_allowed;
- }
- File = Fget (Fp->handle);
- if (file = = NULL) {
- Binder_user_error ("Binder:%d:%d got transaction with invalid FD,%ld\n",
- Proc->pid, thread->pid, Fp->handle);
- Return_error = br_failed_reply;
- Goto err_fget_failed;
- }
- TARGET_FD = Task_get_unused_fd_flags (Target_proc, o_cloexec);
- if (target_fd < 0) {
- Fput (file);
- Return_error = br_failed_reply;
- Goto err_get_unused_fd_failed;
- }
- Task_fd_install (Target_proc, target_fd, file);
- if (Binder_debug_mask & binder_debug_transaction)
- PRINTK (kern_info "fd%ld,%d\n", Fp->handle, TARGET_FD);
- / * todo:fput? * /
- Fp->handle = TARGET_FD;
- } break ;
- ......
- }
- }
- ......
- }
Here, let's take a look at the example of an anonymous shared memory Ashmem (Anonymous shared memory) brief introduction and Learning Plan in this article to get the file descriptor of a file in an anonymously shared-ram scenario. The anonymous shared memory file is created in the server process, and the client passes imemoryservice.getfiledescriptor to get the file descriptor of the anonymous shared memory file created by the server process, which is returned to the server process Back in the process of this file descriptor into the binder driver, the Binder_transact function here. Therefore, the current process of executing the BINDER_TRANSACT function here is the server process, that is, the source process is the server process, and the target process is the client process, which is the process represented here by Target_proc.
function Binder_transaction The Binder object that handles the file descriptor type is in the middle of the for loop.
The first is to obtain binder objects and save them in the local variable fp:
[CPP]View Plaincopy
- fp = (struct flat_binder_object *) (T->buffer->data + *OFFP);
The value of the file descriptor is saved in Fp->handle, and the open file structure for this file descriptor is retrieved by the Fget function:
[CPP]View Plaincopy
- File = Fget (Fp->handle);
The file here is a struct file pointer that represents an open file structure. Note, in a Linux system, open file structure struct file can be shared between processes and is not the same as file descriptors.
Then get a free file descriptor in the target process:
[CPP]View Plaincopy
- TARGET_FD = Task_get_unused_fd_flags (Target_proc, o_cloexec);
Now, in the target process, the open file structure has, and the file descriptor has, then you can associate this file descriptor and this open file structure can be:
[CPP]View Plaincopy
- Task_fd_install (Target_proc, target_fd, file);
Since this binder object is ultimately going to be returned to the target process, it also modifies the value of Fp->handle, which originally represents the file descriptor in the source process and is now changed to the file descriptor of the target process:
[CPP]View Plaincopy
- Fp->handle = TARGET_FD;
This way, the processing of the binder object of the file descriptor type is complete. Once the target process has taken this file descriptor, it can share the open file with the source process.
At this point, the Android system anonymous shared memory using the binder interprocess communication mechanism to achieve inter-process sharing learning is over, the entire Android system anonymous shared memory mechanism of learning has been completed, hoping to help readers, Re-learning the anonymous shared memory mechanism of Android system please go back to the Android system anonymous shared memory Ashmem (Anonymous shared Memories) for a brief introduction and Learning Plan article.
Lao Luo's Sina Weibo: Http://weibo.com/shengyangluo, welcome attention!
An anonymous shared memory for Android Ashmem (Anonymous shared Memories) is a principle of sharing between processes