linux SysV IPC shm共享内存实现

本文详细探讨了Linux系统中SysV IPC共享内存的实现原理,包括分配物理内存、映射到进程地址空间、创建、映射、删除以及移除等步骤。讲解了tmpfs文件系统在共享内存中的作用,以及如何通过信号量实现多进程同步。同时,分析了 shm_file 和 shm 文件数据结构的作用,以及在不同操作中如何维护共享内存的生命周期。
摘要由CSDN通过智能技术生成

共享内存可以使多个进程共享某段内存,由于不需要进程间数据复制,所以是速度最快的IPC。
多个进程访问共享内存时需要同步机制,如进程A往共享内存中写数据时,进程B不能使用共享内存;通常采用信号量同步多进程访问共享内存。

共享内存实现主要有以下几点:
1.分配物理内存
2.将物理内存映射到进程的地址空间;通过修改进程的页表,可以虚拟地址直接访问物理内存
3.进程不再使用共享内存时,取消物理内存在进程地址空间的映射

tmpfs文件系统将所有文件存储在内存(而非硬盘等介质)中;tmpfs将所有的东西存放在内核缓存中,可以根据文件系统中所容纳的文件自动增长和收缩,也可以将不使用的页swap出去。
linux共享内存的实现基于tmpfs文件系统及mmap文件映射;通过在tmpfs中创建文件来获取物理内存,将文件映射到进程地址空间后可以使用虚拟地址访问共享内存。


I.数据结构
include/linux/shm.h

 86 struct shmid_kernel /* private to the kernel */
 87 {
 88         struct kern_ipc_perm    shm_perm;       /* operation perms */
 89         struct file *           shm_file;       /* tmpfs file */
 90         unsigned long           shm_nattch;     /* no. of current attaches */
 91         unsigned long           shm_segsz;      /* size of segment (bytes) */
 92         time_t                  shm_atim;       /* last attach time */
 93         time_t                  shm_dtim;       /* last detach time */
 94         time_t                  shm_ctim;       /* last change time */
 95         pid_t                   shm_cprid;      /* pid of creator */
 96         pid_t                   shm_lprid;      /* pid of last operator */
 97         struct user_struct      *mlock_user;
 98 };

shmid_kernel用于存放共享内存信息
注:
  shm_file存放tmpfs中创建的内存文件,用于分配物理内存;用tmpfs的文件映射功能直接将共享内存映射到进程地址空间

 

ipc/shm.c

  48 struct shm_file_data {
  49         int id;
  50         struct ipc_namespace *ns;
  51         struct file *file;
  52         const struct vm_operations_struct *vm_ops;
  53 };

shm_file_data主要用于保存文件(tmpfs文件)内存映射的虚拟内存操作集vm_ops,进而扩展vm_ops,使某进程已经调用IPC_RMID,其它所有进程detach后能正常释放共享内存IPC资源
注:
  共享内存主要涉及两种文件,tmpfs文件与shm文件;一个共享内存对应一个tmpfs文件,有多少个进程attach到共享内存就有多少个shm文件。
  为什么要在tmpfs文件上层再加shm文件呢?直接将tmpfs文件映射到多个进程地址空间不就能实现内存共享了吗?
  的确,可以将tmpfs文件映射到多个进程地址空间,并能实现内存共享。但是有一种特殊情况,当多个进程attach到共享内存,此时某个进程删除共享内存,为了保证其他进程能继续正常使用共享内存,则暂不能删除共享内存的IPC资源;而所有的进程detach后,tmpfs文件munmap又不能删除IPC资源。
  所以在tmpfs文件上层添加shm文件,用于扩展tmpfs文件映射的vm_ops,来实现所有进程detach后删除共享内存的IPC资源。
  详细代码参见:do_shm_rmid、shm_close
 


II.共享内存创建

 326 /**
 327  * newseg - Create a new shared memory segment
 328  * @ns: namespace
 329  * @params: ptr to the structure that contains key, size and shmflg
 330  *
 331  * Called with shm_ids.rw_mutex held as a writer.
 332  */
 333 
 334 static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 335 {
 336         key_t key = params->key;
 337         int shmflg = params->flg;
 338         size_t size = params->u.size;
 339         int error;
 340         struct shmid_kernel *shp;
 341         int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
 342         struct file * file;
 343         char name[13];
 344         int id;
 345         int acctflag = 0;
 346 
 347         if (size < SHMMIN || size > ns->shm_ctlmax)
 348                 return -EINVAL;
 349 
 350         if (ns->shm_tot + numpages > ns->shm_ctlall)
 351                 return -ENOSPC;
 352 
 353         shp = ipc_rcu_alloc(sizeof(*shp));
 354         if (!shp)
 355                 return -ENOMEM;
 356 
 357         shp->shm_perm.key = key;
 358         shp->shm_perm.mode = (shmflg & S_IRWXUGO);
 359         shp->mlock_user = NULL;
 360 
 361         shp->shm_perm.security = NULL;
 362         error = security_shm_alloc(shp);
 363         if (error) {
 364                 ipc_rcu_putref(shp);
 365                 return error;
 366         }
 367 
 368         sprintf (name, "SYSV%08x", key);
 369         if (shmflg & SHM_HUGETLB) {
 370                 /* hugetlb_file_setup applies strict accounting */
 371                 if (shmflg & SHM_NORESERVE)
 372                         acctflag = VM_NORESERVE;
 373                 file = hugetlb_file_setup(name, size, acctflag,
 374                                         &shp->mlock_user, HUGETLB_SHMFS_INODE);
 375         } else {
 376                 
`sysv_ipc` 和 `posix_ipc` 都是 Python 的模块,用于与共享内存、信号量和消息队列等 POSIX IPC(Inter-Process Communication,进程间通信)机制进行交互。它们之间的区别主要包括以下几个方面: 1. 平台兼容性:`sysv_ipc` 模块仅适用于支持 System V IPC 的系统,如 Linux、Unix 和 macOS。而 `posix_ipc` 模块在支持 POSIX IPC 标准的操作系统上都可以运行,包括 Linux、Unix 和 macOS。 2. 接口和用法:两个模块提供了不同的接口和方法来操作 IPC 机制。`sysv_ipc` 模块使用 System V IPC 的 API,例如 `msgget()`、`msgsnd()`、`msgrcv()` 等来创建、发送和接收消息。而 `posix_ipc` 模块使用 POSIX IPC 的 API,如 `mq_open()`、`mq_send()`、`mq_receive()` 等来操作消息队列。 3. 功能支持:由于 System V IPC 和 POSIX IPC 的设计和实现有所不同,因此两个模块在支持的功能和特性上可能略有差异。例如,在消息队列方面,`posix_ipc` 模块支持消息优先级和非阻塞操作,而 `sysv_ipc` 模块则可能具有其他特定的功能。 需要根据具体的需求和系统环境来选择使用哪个模块。如果目标系统支持 System V IPC,并且需要使用 System V IPC 提供的特定功能,则可以选择使用 `sysv_ipc` 模块。如果目标系统支持 POSIX IPC,并且更关注跨平台兼容性,则可以选择使用 `posix_ipc` 模块。 希望这个解答对你有帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值