Ashmem anonymous shared memory subsystem analysis of Android system (5) - the principle of sharing

statement

The principle of sharing

  In the Android system, each block of anonymous shared memory is described by a file descriptor, and this file descriptor is obtained by opening the device file /dev/ashmem. When two processes need to share an anonymous shared memory, just pass its file descriptor from one process to another.
  But the problem is that in the Linux system, the file descriptor is actually an integer, which is only valid within the scope of the process, that is, two file descriptors with equal values ​​have different meanings in two different processes . In the Linux kernel, each file descriptor corresponds to a file structure (struct file) . The file structure is a kernel object , and each opened file has a corresponding file structure . The relationship between file descriptors, file structures, and files is shown in the figure:
insert image description here
  different file descriptors can correspond to the same file structure, and different file structures can also correspond to the same file. When the application program calls the function open to open a file, the file system will create a file structure and a file descriptor for the file, and finally return the file descriptor to the application program.
  When an application opens the device file /dev/ashmem, the Ashmem driver will create an anonymous shared memory in the kernel for it . Therefore, the relationship between file descriptors, file structures and anonymous shared memory is as shown in the figure:
insert image description here
  The key to sharing anonymous shared memory in two different processes is that the two processes have a file descriptor fd1 and fd2 respectively, which point to the same file structure file1, and this file structure points to an anonymous shared Memory asma. At this time, if the file descriptors fd1 and fd2 of the two processes are mapped to their respective address spaces, then they will map the same anonymous shared memory to their respective address spaces, thus implementing share the same block of anonymous shared memory.

  Question: How to make two file descriptors fd1 and fd2 located in different processes point to the same file structure file1 used to describe anonymous shared memory asma?

  Assume that process p1 first calls the function open to open the device file /dev/ashmem, so that it gets an anonymous shared memory, a file structure fle1 and a file descriptor fd1. Then process p2 requests process p1 to return file descriptor fd1 to it through Binder inter-process communication mechanism, and process p1 returns file descriptor fd1 to process p2 through Binder driver. Since the file descriptor fd1 is only valid in the process p1, the Binder driver cannot directly return the file descriptor fd1 to the process p2. At this time, the Binder driver will create a new file descriptor fd2 in the process p2, making it also point to the file structure file1, and finally return the file descriptor fd2 to the process p2. In this way, the file descriptors fd1 and fd2 point to the same file structure file1, that is, point to the same anonymous shared memory asma.

  The Client component requests the MemoryService service running in another process to return a file descriptor of an anonymous shared memory inside it through the member function getFileDescriptor of an internal MemoryService proxy object. The process is shown in the figure:

Client IMemoryService.Stub.Proxy Binder Driver IMemoryService.Stub MemoryService 1. getFileDescriptor 2. transact 3. onTransact 4. getFileDescriptor 5. ParcelFileDescriptor 6. flat_binder_object 7. flat_binder_object 8. ParcelFileDescriptor Client IMemoryService.Stub.Proxy Binder Driver IMemoryService.Stub MemoryService

  Steps 1 to 4 are the process in which the Client component requests the MemoryService service to return the file descriptor of its internal anonymous shared memory, and steps 5 to 8 are the process in which the MemoryService service returns the file descriptor of its internal anonymous shared memory to Procedure for the Client component.
  In step 5, the MemoryService service encapsulates the file descriptor of the internal anonymous shared memory into a ParcelFileDescriptor object, and then transfers it from the Java layer to the C++ layer.
  In step 6, the ParcelFileDescriptor object being transferred is first converted into a flat_binder_object structure of type BINDER_TYPE_FD, and then transferred to the Binder driver.
  In the seventh step, the Binder driver will process the flat_binder_object structure transmitted in the sixth step, and then return it to the Client component in the eighth step.

  After the Client component obtains the flat_binder_object structure from the Binder driver, it first encapsulates it into a ParcelFileDescriptor object, and then converts it into a FileDescriptor object. Finally, it can use this FileDescriptor object to create a MemoryFile object, which is the MemoryService service internal The anonymous shared memory is mapped to the address space of the process where the Client component is located, thus achieving the purpose of sharing the same anonymous shared memory in different processes.

Guess you like

Origin blog.csdn.net/Xiaoma_Pedro/article/details/131069641