0%

IPC中:共享内存的创建和映射过程

2020年5月4日 下午12:16

  1. 我们来总结一下共享内存的创建和映射过程。
    1. 调用 shmget 创建共享内存。
      1. 先通过 ipc_findkey 在基数树中查找 key 对应的共享内存对象 shmid_kernel 是否已经被创建过,如果已经被创建,就会被查询出来,例如 producer 创建过,在 consumer 中就会查询出来。
      2. 如果共享内存没有被创建过,则调用 shm_ops 的 newseg 方法,创建一个共享内存对象 shmid_kernel。例如,在 producer 中就会新建。
    2. 在 shmem 文件系统里面创建一个文件,共享内存对象 shmid_kernel 指向这个文件,这个文件用 struct file 表示,我们姑且称它为 file1。
      1. 调用 shmat,将共享内存映射到虚拟地址空间。
      2. shm_obtain_object_check 先从基数树里面找到 shmid_kernel 对象。
      3. 创建用于内存映射到文件的 file 和 shm_file_data,这里的 struct file 我们姑且称为 file2。
      4. 关联内存区域 vm_area_struct 和用于内存映射到文件的 file,也即 file2,调用 file2 的 mmap 函数。
      5. file2 的 mmap 函数 shm_mmap,会调用 file1 的 mmap 函数 shmem_mmap,设置 shm_file_data 和 vm_area_struct 的 vm_ops。
    3. 内存映射完毕之后,其实并没有真的分配物理内存,当访问内存的时候,会触发缺页异常 do_page_fault。
      1. vm_area_struct 的 vm_ops 的 shm_fault 会调用 shm_file_data 的 vm_ops 的 shmem_fault。
      2. 在 page cache 中找一个空闲页,或者创建一个空闲页。
  2. 上面流程涉及到内存管理子系统、文件子系统,其实还是比较复杂的,下面我截取了两位读者的总结,对我的理解起到了非常大的作用: