Android shared memory

Time:2020-2-6

Recently, if you encounter any problems, just sort out the documents. It takes a lot of time for the system to write a topic. At present, you still can’t find the time. The reason for this problem is that someone asked about shared memory, saying that binder is based on shared memory, which has been seen on the Internet before. I don’t know the cause of this statement, but it’s totally wrong. A lot of people say that. I’m a bit confused. It’s better to see the implementation of ashmem.

Shared memory

The essence of shared memory is to let multiple processes access the same block of memory space. We know that each process has its own address space, which is inaccessible to each other. However, the memory actually allocated and used by processes comes from physical memory. Processes can access all available physical memory in the kernel space, so multiple processes may use the same physical memory. The easiest way is to use memory file sharing. Create a memory file in memory, and then map to process space through mmap(). Because each process maps the same memory file, the same block of memory is actually used.

There are many shared memory mechanisms in Linux system, but most of them are essentially the same principle as the above simple methods, and they are all accessing the same memory file. Common memory sharing mechanisms include,

  • System V shared memory.
  • POSIX shared memory.
  • Create the shared file through memfd? Create().

System V shared memory

The interfaces used by System V shared memory include: shmget(), shmat(), shmdt(), shmctl(), etc. Shmget () is used to open or create a shared memory area, which is defined as follows.

int shmget(key_t key, size_t size, int shmflg);

Where key is the key value identifying the shared memory, size is the size of the shared memory to be established, shmflg is IPC ﹣ creat, IPC ﹣ excl, etc.

  • When key is IPC “private, a new shared memory will be created.
  • Key is not IPC 〝 private, and the shared memory corresponding to key does not exist. In this case, shmflg will create a new shared memory for IPC 〝 creat or IPC め IPC 〝 excl.
  • If the shared memory corresponding to the key exists, then if shmflg is IPC creat, the shared memory will be opened, and if shmflg is IPC creat IPC exc, an error will be returned.

The shared memory created by shmget () is in the TMPFS file system, which can be shared by multiple processes using the same key. A common way is to use ftok () to get the key of the file, so that the process can open the same file. The shared memory of System V can be viewed through “/ proc / sysvipc / SHM”.

POSIX shared memory

POSIX shared memory uses interfaces such as SHM open(), SHM unlink(), mmap(), etc. This operation mode of shared memory is more similar to the operation of ordinary files. The process uses SHM open() to open or create files, ftruncate() to adjust the file size (when creating a new file), and then use mmap() to map to complete the sharing. Shm_open() is defined as follows.

int shm_open(const char *name, int oflag, mode_t mode);

The definition of shm_open() is similar to that of open(). You can use oflag to specify the properties of creating or opening files. When using SHM open() to create a shared memory file, if the name is just a name rather than a full path, a file will be created under “/ dev / SHM /”, and / dev / SHM is also built on the TMPFS file system.

Created by memfd? Create()

Memfd_create() creates an anonymous file and returns the file descriptor. Like ordinary files, this file can be modified, intercepted, mapped and other operations. The difference is that this file is stored in RAM and created in the TMPFS file system. When using in shared memory, one of the problems is how to let another process get this file? Because memfd_create() creates anonymous files, FD cannot be found in the file system, which makes file sharing difficult. The file name can not be shared as other shared memory mechanisms. A feasible scheme is to pass the file through proc. The anonymous files created by the process are recorded in the proc system and exist in “/ proc / < PID > / FD / < FD >.”. The process of creating a file needs to pass this path to the process that needs to be shared. Opening this path will realize file sharing.

Ashmem

Ashmem characteristics

Instead of using the existing shared memory mechanism on Linux, Android has written a new mechanism, ashmem. Unlike the above mechanism, which is implemented by system call, ashmem is presented as a character device, and the descriptor of shared memory is obtained by operating the character device.

  • Ashmem is based on the virtual memory system shmem of Linux. The shared memory is an anonymous file in the TMPFS file system.
  • Ashmem increases the mechanism of memory management (pin, unpin, purge) and memory recovery (shrink), reducing the complexity of users.
  • Ashmem is closely connected with Android memoryfile. The upper application uses the memoryfile class to complete memory sharing.
  • Memoryfile passes the descriptors of ashmem shared memory through binder. The conversion of descriptors is completed in binder driver.

Steal a picture, and the details will not be analyzed.

https://my.oschina.net/youran…

Android shared memory

Binder and Ashmem

What does binder have to do with shared memory? I don’t think it matters much. In Android system, if you want to share and use ashmem in multiple processes, you need to pass FD of shared memory to other processes, which is implemented by binder. In addition, when using shared memory, it is necessary to transfer control information between processes, which can only be transferred through binder in Android. Besides, it seems that binder has nothing to do with ashmem. This code is worth seeing when binder transfers FD from one process to another.

static void binder_transaction(struct binder_proc *proc,
                   struct binder_thread *thread,
                   struct binder_transaction_data *tr, int reply)
{
        ......
        case BINDER_TYPE_FD: {
            int target_fd;
            struct file *file;
            ......
            //Get the description of the file in the kernel
            file = fget(fp->handle);
            ......
            //Get an unused FD in the target process
            target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
            ......
            //Match the file to the newly acquired FD of the target process
            task_fd_install(target_proc, target_fd, file);
            ......
            fp->binder = 0;
            fp->handle = target_fd;
        } break;
        ......

FD conversion is very convenient in the kernel, but it is very troublesome in user space. User space access to the same anonymous file can be realized through the file under “/ proc / < PID > / FD /”, which is described in memfd_create.

Ashmem is a shared memory mechanism, which can also be considered as a way of IPC. It doesn’t conflict with binder, it should be used in different ways according to different situations.

  • Binder is used to transmit information and small data.
  • Ashmem is used to share big data.
  • Data less than 1m can be transmitted by binder if not frequently used. Because even if you use ashmem, you can’t avoid using binder. It’s better to send the data together.
  • Ashmem prefers to share pure data. If the control information is put into shared memory, it will increase the complexity of data maintenance, and the gain is not worth the loss.