【Linux进程间通信(六)】深入理解 System V IPC

         (一)引入

(二)IPC 命名空间

(三)ipc_ips结构体

(四)ipc_id_ary结构体

(五)kern_ipc_perm结构体

(六)操作系统对IPC资源是如何管理的


(一)引入

在前三篇的博客中,我介绍了System V IPC在Linux中的三种方式:共享内存、消息队列以及信号量。观察这三种IPC资源的内核数据:

共享内存:

           struct shmid_ds {struct ipc_perm shm_perm;    /* Ownership and permissions */size_t          shm_segsz;   /* Size of segment (bytes) */time_t          shm_atime;   /* Last attach time */time_t          shm_dtime;   /* Last detach time */time_t          shm_ctime;   /* Creation time/time of lastmodification via shmctl() */pid_t           shm_cpid;    /* PID of creator */pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */shmatt_t        shm_nattch;  /* No. of current attaches */...};

 消息队列:

           struct msqid_ds {struct ipc_perm msg_perm;   /* Ownership and permissions */time_t          msg_stime;  /* Time of last msgsnd(2) */time_t          msg_rtime;  /* Time of last msgrcv(2) */time_t          msg_ctime;  /* Time of creation or lastmodification by msgctl() */unsigned long   msg_cbytes; /* # of bytes in queue */msgqnum_t       msg_qnum;   /* # number of messages in queue */msglen_t        msg_qbytes; /* Maximum # of bytes in queue */pid_t           msg_lspid;  /* PID of last msgsnd(2) */pid_t           msg_lrpid;  /* PID of last msgrcv(2) */};

信号量:

           struct semid_ds {struct ipc_perm sem_perm;  /* Ownership and permissions */time_t          sem_otime; /* Last semop time */time_t          sem_ctime; /* Creation time/time of lastmodification via semctl() */unsigned long   sem_nsems; /* No. of semaphores in set */};

 我们不难发现,这三种IPC资源的数据结构中都包含了一个结构体ipc_perm,这就需要我们思考了,为什么要这么设计呢?跟着我的脚步往下走吧。

 上图是在Linux内核中管理System V IPC的部分,接下来我将依照这个图来进行讲解。

(二)IPC 命名空间

在Linux内核中存在一个IPC命名空间,它是一种用于隔离不同进程间通信资源的机制。IPC命名空间允许在同一主机上创建多个独立的IPC资源集合,每个 IPC 命名空间都有自己的信号量、消息队列和共享内存等 IPC 对象。

通过IPC命名空间,可以实现不同进程之间的通信资源隔离,避免不同进程之间的通信资源相互干扰。

IPC命名空间里面用struct ipc_ids的结构体数组来管理各种IPC资源,该结构体数组中的每一个元素都代表一个IPC资源,比如ids[0]可能代表信号量,ids[1]可能代表消息队列等。

struct ipc_namespace{atomic_t count; struct ipc_ips ids[3];......
};

(三)ipc_ips结构体

struct ipc_ids结构体内容如下

struct ipc_ids {struct ipc_id_ary *entries;int in_use;int max_id;int seq;struct ipc_id_ary *free;struct ipc_id_ary *in_use_next;struct ipc_id_ary *in_use_prev;
};

  • entries:存储 IPC 对象信息的数组,每个元素是一个 ipc_id_ary 结构体,用于存储特定类型的 IPC 对象的 id。
  • in_use:当前已经被使用的 IPC 对象数量。
  • max_id:当前 IPC 对象的最大 id。
  • seq:IPC 对象的序列号。
  • free:空闲的 ipc_id_ary 结构体链表,用于存储可以被重用的 IPC 对象 id。
  • in_use_next 和 in_use_prev:指向已经被使用的 ipc_id_ary 结构体的链表的下一个和上一个元素。

(四)ipc_id_ary结构体

 struct ipc_id_ary结构体内容如下:

struct ipc_id_ary {struct ipc_ids *ids;int in_use;int seq;struct kern_ipc_perm *p[IPCID_ARRAY_ENTRIES];
};
  • ids:指向包含该 ipc_id_ary 结构体的 ipc_ids 结构体的指针,用于确定所属的 IPC 对象类型。
  • in_use:表示该 ipc_id_ary 结构体当前是否被使用。
  • seq:IPC 对象的序列号。
  • p:一个长度为 IPCID_ARRAY_ENTRIES 的指针数组,用于存储指向 kern_ipc_perm 结构体的指针。kern_ipc_perm 结构体包含了 IPC 对象的权限信息等。

(五)kern_ipc_perm结构体

  kern_ipc_perm结构体内容如下:

struct kern_ipc_perm {key_t key;              // IPC 对象的键kuid_t uid;             // 拥有者的用户 IDkgid_t gid;             // 拥有者的组 IDkuid_t cuid;            // 创建者的用户 IDkgid_t cgid;            // 创建者的组 IDumode_t mode;           // 权限模式unsigned int seq;       // 序列号
};

(六)操作系统对IPC资源是如何管理的

可以发现,kern_ipc_perm跟共享内存、消息队列以及信号量中的ipc_perm的内容一致。

 现在我们可以对操作系统如何管理IPC资源来进行总结了。

设计者通过先描述,再组织的思想将各种IPC资源通过结构体数组的数据结构来进行管理,所以对IPC资源的管理就变成了对数组的增删查改。

接下来我将通过 操作系统是如何查找一个特定的IPC对象(这里我以消息量为例子)的权限信息的,来讲解IPC管理。

  1. 用户进程传递IPC对象的唯一标识符给系统,系统根据这个标识符进行查找。

    系统使用IPC对象的标识符作为索引,在全局的ipc_ids数组中进行查找。
  2. 系统根据IPC对象的标识符,在全局的ipc_ids数组中查找到对应的ipc_ids结构体,获取IPC对象的全局序列号。

    系统根据IPC对象的标识符计算出在ipc_ids数组中的位置,获取对应的ipc_ids结构体。
  3. 在ipc_ids结构体中的entries数组中,根据IPC对象的全局序列号找到对应的ipc_id_ary结构体。

    系统根据IPC对象的全局序列号,在entries数组中查找对应的ipc_id_ary结构体。
  4. 在ipc_id_ary结构体中,根据IPC对象的全局序列号和局部序列号,通过p指针数组找到要查找的IPC对象的位置。

    系统根据IPC对象的全局序列号和局部序列号,在p指针数组中找到对应的IPC对象的位置。
  5. 最终在kern_ipc_perm *p数组中找到了目标IPC对象的位置,可以对该IPC对象进行操作。

    系统根据在ipc_id_ary结构体中找到的位置,定位到kern_ipc_perm *p数组中对应的IPC对象。

通过以上步骤,系统可以根据用户传递的IPC对象的唯一标识符,通过一系列的查找和计算,最终定位到系统中具体的IPC对象,确保进程可以安全地访问和操作IPC资源。这种查找过程涉及到对全局数据结构的索引和计算,以及多层的查找和定位操作。

而最后找到的kern_ipc_perm结构体虽然和三种IPC方式中的ipc_perm结构体名称不同,但其内容都是相同的,操作系统会利用类型转换,通过kern_ipc_perm结构体就可以访问其他三种IPC方式的结构体了,这就类似于一种多态的思想,通过父类指针,访问子类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/679668.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于Anaconda常用的命令

常用命令 查看当前环境下的环境:conda env list查看当前conda的版本;conda --version conda create -n your_env_name pythonX.X(2.7、3.6等)命令创建python版本为X.X。名字为your_env_name的虚拟环境。your_env_name文件可以在Anaconda安装…

嵌入式学习69-C++(Opencv)

知识零碎: QT的两种编译模式 1.debug 调试模式 …

用HAL库改写江科大的stm32入门例子_9-2 利用中断进行串口通讯

电路和 《用HAL库改写江科大的stm32入门例子_9-1》一致。 我们在whlie循环当中,不断查询端口,获取数据,存放到一个数组当中,同时回显给电脑上。这种方法耗费cpu,还是用中断进行串口通讯更合理。 基本操作看到一遍写得比较清晰的博客&#x…

SF 不消费buffer

1、请求合成请求vsync MessageQueue.cpp 返回nextWakeupTime struct ArmingInfo { nsecs_t mActualWakeupTime; nsecs_t mActualVsyncTime; nsecs_t mActualReadyTime; }; 在schedule 请求vsync 时会根据算法计算出nextVsyncTime时间&#…

Failed to get DISPLAY: Error: All configured authentication methods failed 解决方法

Vscode一连接远程服务器就报错: 这个时候我们是无法使用Xming显示图像的。 尝试后发现,Windows电脑能够ping通服务器ip,但是服务器ping不通Windows电脑: 在网上查攻略,设置Windows电脑ip地址白名单,但…

HCIP的学习(13)

第五章,重发布和路由策略 重发布 ​ 在路由协议的边界设备上,将某一种路由协议的路由信息引入到另一种路由协议中,这个操作被称为路由引入或者路由重分发。----技术本质为重发布。 条件 必须存在ASBR设备(路由边界设备&#x…

YOLOv5改进(二)BiFPN替换Neck网络

前言 针对红绿灯轻量化检测,上一节使用MobileNetv3替换了主干网络,本篇将在使用BiFPN替换Neck的方式优化算法~ 往期回顾 YOLOv5改进(一)MobileNetv3替换主干网络 目录 一、BiFPN简介二、改进方法一第一步:在common.…

案例|200多套设备实时监测,守护江西彰湖水库安全

中型水库作为水利建设的重要组成部分,在防洪、供水、农业灌溉、改善民生和生态效益等方面都具有重要意义。国务院发布《关于切实加强水库除险加固和运行管护工作的通知》,重点提出要提升信息化管理能力,要加快建设水库雨水情测报、大坝安全监…

【C++】二叉搜索树(手撕插入、删除、寻找)

一、什么是二叉搜索树 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所有节点的值都大于根节点的值它的左…

docker部署常用工具

1.创建mysql docker run -p 3306:3306 --name mysql -v /home/mysql/conf:/etc/mysql/mysql.conf.d -v /home/mysql/log:/var/log/ -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD2022qwer -d mysql:5.7 而后再执行升级: docker update --restar…

二叉树习题汇总

片头 嗨!大家好,今天我们来练习几道二叉树的题目来巩固知识点,准备好了吗?Ready Go ! ! ! 第一题:二叉树的最大深度 解答这道题,我们采用分治思想 1. 递归子问题:左子树的高度和右子树的高度 …

MQTT服务搭建及python使用示例

1、MQTT协议 1.1、MQTT介绍 MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模式的通信协议,通常用于物联网设备之间的通讯。它具有低带宽、低功耗和开放性等特点,适合在网络带宽有限或者网络连接不稳定…