趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
85459 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

41 | IPC(中):不同项目组之间抢资源,如何协调?

IPC_SHM_IDS
IPC_MSG_IDS
IPC_SEM_IDS
shmem_getpage_gfp
shmem_fault
shm_vm_ops
shmem_mmap
shmem_file_operations
shm_obtain_object_check
ipc_addid
shmem_kernel_file_setup
kvmalloc
kern_ipc_perm
next_id
idr
rw_semaphore
seq
in_use
ids[3]
do_shmat
shmat
newseg
ipcget_public
ipcget
shmget
shm_obtain_object
msq_obtain_object
sem_obtain_object
ipc_obtain_object_idr
struct ipc_ids
shm_ids
msg_ids
sem_ids
ipc_namespace
共享内存映射
创建共享内存
内核里面的处理
IPC(中):不同项目组之间抢资源,如何协调?

该思维导图由 AI 生成,仅供参考

了解了如何使用共享内存和信号量集合之后,今天我们来解析一下,内核里面都做了什么。
不知道你有没有注意到,咱们讲消息队列、共享内存、信号量的机制的时候,我们其实能够从中看到一些统一的规律:它们在使用之前都要生成 key,然后通过 key 得到唯一的 id,并且都是通过 xxxget 函数。
在内核里面,这三种进程间通信机制是使用统一的机制管理起来的,都叫 ipcxxx。
为了维护这三种进程间通信进制,在内核里面,我们声明了一个有三项的数组。
我们通过这段代码,来具体看一看。
struct ipc_namespace {
......
struct ipc_ids ids[3];
......
}
#define IPC_SEM_IDS 0
#define IPC_MSG_IDS 1
#define IPC_SHM_IDS 2
#define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS])
#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
#define shm_ids(ns) ((ns)->ids[IPC_SHM_IDS])
根据代码中的定义,第 0 项用于信号量,第 1 项用于消息队列,第 2 项用于共享内存,分别可以通过 sem_ids、msg_ids、shm_ids 来访问。
这段代码里面有 ns,全称叫 namespace。可能不容易理解,你现在可以将它认为是将一台 Linux 服务器逻辑的隔离为多台 Linux 服务器的机制,它背后的原理是一个相当大的话题,我们需要在容器那一章详细讲述。现在,你就可以简单的认为没有 namespace,整个 Linux 在一个 namespace 下面,那这些 ids 也是整个 Linux 只有一份。
接下来,我们再来看 struct ipc_ids 里面保存了什么。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Linux内核中的IPC机制统一管理了进程间通信的三种方式:消息队列、共享内存和信号量。这些机制在使用前都需要生成唯一的id,并且通过xxxget函数进行访问。在内核中,这三种进程间通信机制都被统一管理起来,通过一个包含三项的数组来维护。每一项对应一个进程间通信方式,分别可以通过sem_ids、msg_ids、shm_ids来访问。这种机制将信号量、消息队列、共享内存抽象为ipc类型进行统一处理,类似于面向对象编程中的抽象类和实现类的概念。通过这种机制,可以更好地管理和处理进程间通信,为不同项目组之间抢资源提供了更好的协调方式。 文章详细介绍了创建共享内存的系统调用和具体实现过程,包括ipcget函数的调用、newseg函数的具体实现以及共享内存和文件的关联过程。通过这些内容,读者可以深入了解Linux内核中共享内存的创建和管理机制,为进程间通信提供了更清晰的认识。文章还对共享内存的映射到虚拟地址空间进行了详细解析,包括调用shmat将共享内存映射到虚拟地址空间的具体过程,以及内存映射的实现细节。 总的来说,本文通过深入解析Linux内核中的共享内存创建、管理和映射过程,为读者提供了全面的技术视角。同时,文章还鼓励读者对消息队列的程序进行解析,以加深对IPC机制的理解。这篇文章适合对Linux内核进程间通信机制感兴趣的技术人员阅读,能够帮助他们更好地理解和应用进程间通信的相关知识。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(14)

  • 最新
  • 精选
  • book尾汁
    补充下该查了下file是VFS框架的一个基本概念,一切皆文件指的就是这个,f,然后在这个file下面会有各种各样的实现,比如设备是文件 sock是文件 pipe是文件 共享内存也是文件,file结构体里面都是一些通用的属性,而private_data里面是一些各个披着文件外衣的各种结构体的一个独特的东西,因此这里会有两个file,vm_file就是这个外壳,其private_data里就是共享内存的相关数据

    作者回复: 对的,

    2020-04-28
    8
  • book尾汁
    共享内存: 创建共享内存,通过shmget系统调用来创建一个共享内存,主要是通过key来创建一个struct kern_ipc_perm,信号量 队列和共享内存的结构都是一样的,可以通过强制类型转换来转化成任意一个类型.然后接下来去填充这个结构,然后将一个文件与共享内存关联,内存映射有两种方式一种是匿名映射 一种是映射到一个文件,物理内存是不能共享的,文件可以跨进程共享,所以要映射到文件.但这里的文件是一个特殊的文件系统内存文件系统上的文件,这个内存文件系统也会在系统初始化的时候注册 挂载, 该文件也有目录项和inode以及其fs_operation,然后会将新创建的共享内存对象加入到shm_ids基数上,并将其加到当前进程的sysvshm队列中. 现在共享内存其实还只是内核中的一个结构体,我们只有共享内存的id,要想使用共享内存还要通过id来将其映射到使用者的用户态的进程空间中,通过shmat系统调用可以做到这一点,该系统调用的主要工作如下: 1 通过共享内存的ip在 shm_ids基数树上找到该共享内存的结构体,然后取出内存文件系统里file并将其赋值给新创建的struct shm_file_data->file,这里我们已经有了可以共享的文件"file",然后在用户进程虚拟空间的mmap映射区分配一个vm_area struct来做文件映射就可以了,将vm_area_struct里的vm_file的private_data指向shm_file_data,为什么不能直接用file呢?private_data貌似只有共享内存才有用,不太理解,可能因为vm_file有其独特的file_operation的问题吧,两个file'虽然可以是同一类结构体,但差异还是很大.在创建vm_file的过程中应该可以找到答案,略过,映射内存时还会将vm_area的vm_ops先指向shmem_vm_ops,然后在指向shm_vm_ops, 将shm_file_data的vm_ops指向shmem_vm_ops即内存文件系统的文件的vm_ops,到这里就完成了.后面进程读或写数据时,如果对应的页表项没有建立会触发缺页异常,跟之前的缺页异常流程差不多,最终会调用内存文件系统的缺页异常函数来分配对应的物理页,并建立页表项.

    作者回复: 赞

    2020-04-27
    3
    5
  • Amark
    老师有没有什么通俗易懂的资料,您将的太专业了

    作者回复: 的确比较硬核,我实在是没办法再比喻了

    2019-07-02
    2
  • 不一样的烟火
    听完了 快点更新😁

    作者回复: 牛

    2019-07-01
  • Spring
    文章一遍看不懂但底下总结的图很好,终于明白了为什么需要两个file。file1是shmem内存文件系统里的文件,file2是进程虚拟内存里映射的文件,所以file1是属于共享内存的,file2是属于某个进程的。
    2019-09-27
    1
    20
  • 小橙子
    工作了几年 ,业务代码写多了,框架与API调来调去的,遇到很多疑难杂症,还是不明所以。 回过头再看下 操作系统真是核心,很多人说操作系统就是功夫里面的易筋经,内功章法。学习了操作系统,再看很多其他的技术,感觉更自然,理解的更深刻了。一直想读内核代码,但是啃起来很费劲,这个专栏一直再看,越看越喜欢,很多篇章都会反复的看。相信看完专栏后,再去看一些深入理解linux内核,会清晰很多。
    2019-11-06
    1
    12
  • 珠闪闪
    文章两遍读下来蒙蒙的,最后对着总结图把共享内存的创建和在用户态映射的流程理顺了。关键就是因为共享内存刚开始申请的物理内存无法在进程中共享,所以先要把物理内存的shmid_kernel对应到shmem文件系统的一个文件,这样shmem中的文件可以再进程中共享;然后在shmat函数时,相当于将shm映射到shmem的file2,先映射到shmem文件系统的文件file1,然后再通过file1的mmap函数完成shm_file_data和vm_area_struct的ops设置。这样内存映射完毕后,并没有真的分配物理内存,当访问内存会触发缺页异常。然后vm_area_struct的vm_ops的shm_fault会调用shm_file_data的vm_ops的shmem_fault。最后在page cache中找一个空闲页,或者创建一个空闲页。
    2020-03-08
    1
    7
  • 小鳄鱼
    为了统一操作入口:一切皆文件。构建了各种各样的“文件系统”。共享内存文件系统,硬盘文件系统(ext4等),设备文件系统,相信还有各种各样的文件系统!虽然感觉复杂了,但是实际的场景本来就不简单。反而统一入口之后,“上层建筑”的开发人员不再需要关系底层的具体实现,从而实现并行开发,独立维护。
    2022-06-02
    1
  • NeverSeeYouAgainBUG
    哎呀超哥,深入浅出啊深入浅出啊。关键在 浅出,要好好总结,
    2022-06-12
  • Geek_2b44d4
    这个page cache 跟swap的选择时机是怎样的?
    2022-05-09
收起评论
显示
设置
留言
14
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部