ipc_namespace_马学的博客-程序员秘密_ipc名称空间

技术标签: kernel  namespace  docker  

1      IPC概述

linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。Linux则把两者继承了下来,如图示:

linux下进程间通信的几种主要手段简介:

1)管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;

2)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);

3)报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

4)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

5)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

6)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

 

2      IPC namespace

2.1      功能

Ipc namespace的作用是使划分到不同ipc namespace的进程组通信上隔离,无法通过消息队列、共享内存、信号量方式通信,但没有对所述所有IPC通信方式隔离。

2.2      实现

下面我们以消息队列和共享内存为例进行说明

2.2.1      消息队列

IPC命名空间是一个扁平的结构,在ipc_namespace.h中定义了IPC命名空间的数据结构:

其中最关键的就是

每一个struct ipc_ids结构描述了一类IPC资源,在IPC名空间之前,内核定义了三个全局的ipc_ids结构实例,分别代表信号量、消息队列和共享内存。

这就意味着所有的进程都能够通过这三个全局资源进行通信。IPC命名空间取消了这三个全局实例,放入了ipc_namespace中,通过三个宏访问某一个IPC命名空间的IPC资源:




        这意味着不同的IPC命名空间不能访问彼此的ipc_ids成员,先看一下ipc_ids的作用,其定义在ipc_namespace.h中

接下来再看一下struct idr的定义,在idr.h中:

一并将idr_layer的第一列举出来,在idr.h中:

结合idr和idr_layer结构,可以看得出来,idr是一棵树,只不过是每个节点都有32个叶子节点的大树。接下来结合消息队列分析下idr的作用。

分析下创建一个消息队列的过程:

接下来调用了do_msgget函数,传入的第一个参数是current->nsproxy->ipc_ns,结合前面的知道是创建该消息队列的进程的IPC命名空间;第二个参数key:消息队列关联的键;msgflg:消息队列的建立标志和存取权限。

这里的ns就是上面传下来的当前进程的IPC命名空间,msg_ops是一个操作集合,根据msgflg确定该执行集合中的哪个函数。Key和msgflg被保存到了msg_params中,然后调用了msg_ids(ns)宏,根据前面的介绍:

知道是获取了IPC命名空间中的ipc_ids的消息队列相关的实例。

根据上面的注释可以看到如果,key=0那么接下来调用ipcget_new创建一个私有的消息队列,通常key的值都会大于0,所以这里选择ipcget_public函数分析,传给ipcget_public的参数仍然是IPC命名空间;ipc_ids实例;msg操作集;key和msgflg,req_id=-1。

关注下蓝色的函数idr_pre_get,这个函数主要是为前面说到的idr树分配内存,并创建好这棵树,具体过程不作分析。

接下来调用了一个关键的函数

这里看到了上面传入的IPC命名空间里消息队列相关的ipc_ids实例,这个函数执行后返回的是一个kern_ipc_perm结构的指针,struct kern_ipc_perm是三类IPC资源中共同的一部分,看一下信号量、消息队列和共享内存数据结构的定义:


有图中蓝色的部分看到,都定义了一个kern_ipc_perm结构,也就是说找到了kern_ipc_perm结构的实例也就找到了信号量或者消息队列或者共享内存的实例。继续看ipc_findkey函数:

分析蓝色部分的idr_find函数,传入的参数是ids中的idr成员ipcs_idr,也就是这个ids管理的idr树:

可以看得出来这两个函数是通过key到ids管理的idr树中查找和key相符合的kern_ipc_perm实例,对于新创建的消息队列,这里查找肯定会返回空。继续回到ipcget_public函数中:

如果返回空,那么最后调用了msg操作集中的getnew函数,

前面分析过getnew被赋值为newque,分析下newque函数:


分配一个消息队列,包含了一个kern_ipc_perm结构。


这个函数是关键,前面分配的消息队列的kern_ipc_perm结构被作为参数传入&msq->q_perm,ids实例也被作为参数传入,ipc_addid函数不具体分析了,起作用就是在&msg_ids(ns)管理的idr树中找到一个空闲节点,将&msq->perm存入这个节点中,同时返回这个节点的序号,也就是这个函数的返回值给id,最后这个函数返回的msq->q_perm.id也就是节点的序号,最后msgget返回的句柄也就是这个id号,程序可以用这个id号进行发送消息。

        总结起来,命名空间和各类IPC资源之间的关系如下图:

2.2.2      共享内存

共享内存的创建过程与msg基本相同,只是getnew指向的函数改为newseg。

前面一些初始化的操作,最关键的步骤就是shmem_file_setup()

 

 

在全局的tmpfs中申请一个inode并设置文件大小,申请一个sturct file和这个inode绑定并存储到struct shmid_kernel中,后面其他进在获取这块共享内存时就从shmid_kernel开始的。

 

下面我们看下其他进程如果获取这块共享内存:

系统调用接口shmat

很明显关键操作是do_shmat,这个函数的入参ret返回的就是我们希望得到的,共享内存在本进程对应的虚拟地址,下面看下它是如何实现的

通过current->nsproxy->ipc_ns获取当前IPC命名空间,再获取前述struct shmid_kernel,所以这一步就保证了只有在相同命名空间内的进程才能获取ID为shmid的共享内存。然后再申请一个struct file和上一步的inode绑定并设置ops。

接下来先检查下当前进程是否有足够虚拟地址空间来完成这次映射,最后调用do_mmap完成实际的映射,返回映射地址user_addr传给用户态。 不同进程获取的这个地址可能不一样,但真实的物理地址都是指向前述newseg申请的tmpfs。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tanzhe2017/article/details/81001682

智能推荐

System.currentTimeMillis() 和sleep 存在误差原因与解决方案_党玉涛的博客-程序员秘密

System.currentTimeMillis() 与sleep()存在误差。精度跟系统相关,10ms-15ms为常见误差,多媒体操作多用  System.nanoTime()  返回纳秒值。即用  System.nanoTime()  /1000000L 替换  System.currentTimeMillis() 参考jdk文档:在指定的毫

浅谈网页基本性能优化规则小结_weixin_34326429的博客-程序员秘密

这篇文章主要介绍了浅谈网页基本性能优化规则小结的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧针对浏览器网页的一些优化规则页面优化静态资源压缩借助构建工具(webpack、gulp)适当压缩图片、脚本及样式等网页静态资源。CSS雪碧图、base64内联图片将站内小图标合并成一张图,使用cs...

新建django项目提示:python: can't open file 'django-admin.py': [Errno 2] No such file or directory_youmypig的博客-程序员秘密

方法1.将django-admin.py 文件拷贝到自己的项目下,新建即可成功,原因本人还没找到,如果谁找到了帮忙说下是为什么不能新建。我的环境变量设置了。

Helm简介_迷途的攻城狮(798570156)的博客-程序员秘密_helm是什么

Helm简介 这几天花了不少时间在helm的学习之上,目前还不能熟练运行,很多东西都停留在记忆层面。整理这篇文章为加深印象,也便于后续实践的过程中参考和查询——记性不好。1、简介 Helm is the best way to find, share, and use software built for Kubernetes.Helm之于Kubernetes好比y...

Python通过文件头来判断文件的真实类型_shuifa2008的博客-程序员秘密

###  # 文章:Python通过文件头来判断文件类型  # 作者:http://aminby.net  ###    import struct    # 支持文件类型  # 用16进制字符串的目的是可以知道文件头是多少字节  # 各种文件头的长度不一样,少半2字符,长则8字符  def typeList():      return {

MyCat安装与测试教程 超详细!_weixin_30624825的博客-程序员秘密

MyCat安装与测试教程 超详细!MyCat基础知识一、什么是MYCAT? 1. 一个彻底开源的,面向企业应用开发的大数据库集群 2. 支持事务、ACID、可以替代MySQL的加强版数据库 3. 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 4. 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server 5. 结合传统...

随便推点

Java Web 学习路线_光明顶上的5G的博客-程序员秘密

Java Web 学习路线实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了。大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算是学完了,找工作对你来说或许还有些距离,而我已经有了自己喜欢的工作,从一个自学狂人的角度,我只能给你比较实用但有限的建议:如果 .Net 你是刚入门, 建议转学 J...

利用正则爬取百度贴吧;;反爬虫措施_一只迟到的程序猿狗狗的博客-程序员秘密_使用正则表达式和文件操作爬取并保存“百度贴吧”某帖子内容(该帖不少于5页)。

例子 爬取nba百度贴吧:# coding: utf-8# 引入请求包import requests# 引入正则表达式包import re# 1.准备urlurl = 'https://tieba.baidu.com/p/5082744218'# 2.获取网页源代码,发起请求接收响应response = requests.get(url)html = response

操作系统实验报告_独宠。的博客-程序员秘密_操作系统 实验报告

调度算法一、实验目的1.理解操作系统进程管理中进行进程调度的过程和编程方法,创建进程控制块PCB。2.理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。掌握几种调度算法。理解几种进程调度的方式用代码将几种进程调度的方式表现出来二、实验原理(1)先到先服务:按照进程提交给系统的先后次序来进行调度。(2)短作业优先:按照进程所要求的运行时间来衡量。(3)时间片轮转:根据先来先服务排序,以一个时间片为单位,依次执行不同的进程。(4)响应比高者优先(HRRN)调度算法,为每个作业

(转)CEF3研究_rathome的博客-程序员秘密

一、Off-Screen Rendering 脱屏绘制CEF的脱屏渲染并不创建源生的浏览器窗口,而是CEF提供主应用程序在无效区域和像素buffer里渲染,然后主应用程序通过鼠标、键盘和焦点事件通知CEF。 脱屏渲染现在不支持图层混合加速图层混合加速。脱屏渲染要窗口浏览器一样接受相同的通知,包括生命周期通知等,为了使用脱屏渲染:实现CefRenderHandler接口,所有方法是必需的,除非另有指

Qt静态编译教程(完整版)_nickzzw的博客-程序员秘密_qt静态编译

出处:Qt默认的编译方式是动态编译的,但是有时候你编写的程序要发布出去,带很多动态库文件是很繁琐的,此时就需要静态编译你的程序,Qt要实现静态编译必须库文件也是静态编译的,可以用这个命令编译静态库:配置编译选项打开 %QtDir%\mkspecs\win32-g++\qmake.conf (%QtDir%为Qt库所在目录)在QMAKE_LFLAGS后面加

使用Django搭建一个博客系统5.1——学习一下查询集(QuerySet对象管理器)_千羽之森的博客-程序员秘密

QuerySet方法的主要功能是查询,用于查询后台数据库中的信息,通过manage.py可以shell进去看到一些条件来查询。而且我们在views.py中写的一些方法,比如获取文章列表,获取文章详情页。都是通过这个来的。不过在views.py中没有看到相关语句,是在模板中吗???...