Posix与System V IPC

news/2024/5/17 19:04:22/文章来源:https://blog.csdn.net/weixin_50866517/article/details/127096564

Posix与System V IPC

  • 一、Posix IPC
  • 1.概述
    • 2.IPC名字
      • 3.px_ipc_name函数
        • 3.创建与打开IPC通道
          • 4.IPC权限
    • 二、System V IPC
  • 1.概述
    • 2.key_t键和ftok函数
      • 3.ipc_perm结构
        • 4.创建与打开IPC通道
          • 5.IPC权限
          • 6.标识符重用
          • 7.ipcs和ipcrm程序
          • 8.内核限制

一、Posix IPC

1.概述

三种类型的IPC合称为"Posix IPC":

  1. Posix消息队列;

  2. Posix信号量;

  3. Posix共享内存区;

在这里插入图片描述

2.IPC名字

三种类型的Posix IPC都使用"Posix IPC名字 ” 进行标识。mq_open、 sem_open和shm_open这三个函数的第一个参数就是这样的一 个名字,它可能是某个文件系统中的一 个真正的路径名,也可能不是。

Posix.1描述Posix IPC名字的:

  1. 必须符合已有的路径名规则(必须最多由PATH_MAX个字节构成,包括结尾的空字节)。

  2. 若以斜杠符开头,那么对这些函数的不同调用将访问同 一 个队列。如果它不以斜杠符开头,那么效果取决于实现。

  3. 名字中额外的斜杠符的解释由实现定义。

由于移植性问题不能都兼容到,应该把Posix IPC名字的#define行放在一个便于修改的头文件中,这样程序转移到另一个系统上,只需修改头文件。Posix.1定义了三个宏:

S_TYPEISMQ(buf);
S_TYPEISSEM(buf);
S_TYPEISSHM(buf);
  1. 参数buf是指向某个stat结构的指针,其内容由fstat、lstat或stat这三个函数填入。
  2. 若所指定的lPC对象(消息队列、信号囊或共享内存区对象)是作为一种独特的文件类型实现的,而且参数所指向的stat结构访问这样的文件类型,那么这三个宏计算出 一 个非零值。否则,计算出的值为0。
  3. 项目3

3.px_ipc_name函数

自定义px_ipc_name函数解决移植性问题的方法,定位Posix IPC名字而添加上之前的前缀目录。

char *px_ipc_name(const char *name);
//name不能有任何斜杠符,例:
px_ipc_name("test");

函数原型:

char * px_ipc_name(const char *name)
{char	*dir, *dst, *slash;if ( (dst = malloc(PATH_MAX)) == NULL)return(NULL);//可以使用环境变量覆盖默认目录if ( (dir = getenv("PX_IPC_NAME")) == NULL) {
#ifdef	POSIX_IPC_PREFIXdir = POSIX_IPC_PREFIX;		/* 来自“config.h”*/
#elsedir = "/tmp/";				/* default */
#endif}/* dir必须以斜杠结尾 */slash = (dir[strlen(dir) - 1] == '/') ? "" : "/";snprintf(dst, PATH_MAX, "%s%s%s", dir, slash, name);return(dst);			/* 调用方可以释放()此指针*/
}

3.创建与打开IPC通道

mq_open、sem_open和shm_open这三个创建或打开个 IPC 对象的函数 ,它们的名为oflag的第二个参数指定怎样打开所请求的对象。与标准open函数的第二个参数类似。下图给出了可组合构成该参数的各种常值。
在这里插入图片描述

  1. 前3行指定怎样打开对象:只读、只写或读写。

  2. 消息队列能以其中任何一种模式打开。

  3. 信号量的打开不指定任何模式(任意信号量操作,都需要读写访问权)。

  4. 共享内存区对象不能以只写模式打开。

  5. O_CREAT:若不存在则创建由函数第一个参数所指定名字的消息队列、信号量或共享内存区对象(同时检查O_EXCL标志)。

  6. O_EXCL:如果该标志和O_CREAT一起指定,那么IPC函数只在所指定名字的消息队列、信号量或共享内存区对象不存在时才创建新的对象。若该对象已经存在,而且指定了O_CREATIO_EXCL,那么返回一个EEXIST错误。

  7. O_NONBLOCK:该标志使得一个消息队列在队列为空时的读或队列填满时的写不被阻塞

  8. O_TRUNC:若以读写模式打开了一个已存在的共享内存区对象,那么该标志将使得该对象的长度被截成0。

创建新的消息队列、信号量或共享内存对象时,至少需要另外一个称为mode的参数,该参数指定权限位,如下图常值按位形成的。
在这里插入图片描述

下图展示了打开IPC对象的真正逻辑流程:

在这里插入图片描述
下图是展示上图的另一种方式:

在这里插入图片描述

4.IPC权限

新的消息队列、有名信号显或共享内存区对象是由其oflag参数中含有O_CREAT标志的mq_open、sem_open或shm_open函数创建的。权限位与这些IPC类型的每个对象相关联,就像它们与每个Unix文件相关联一样。

当同样由这三个函数打开已存在的消息队列、信号拭或共享内存区对象时(或者未指定O_CREAT,或者指定了O_CREAT但没有指定O_EXCL,同时对象已经存在),将基于如下信息执行权限测试:

  1. 创建时赋予该IPC对象的权限位;

  2. 所请求的访间类型(O_RDONLY、O_WRONLY或O_RDWR);

  3. 调用进程的有效用户ID、有效组ID以及各个辅助组ID(前提支持)。

大多数Unix内核按如下步骤执行权限测试:

  1. 若当前进程的有效用户ID为0(超级用户),那就允许访问。

  2. 在当前进程的有效用户ID等于该IPC对象的属主ID的前提下,若相应的用户访问权限位已设置,那就允许访问,否则拒绝访问。(相应的用户访问权限位:若当前进程为读访问而打开该IPC对象,那么用户读权限位必须设置;若当前进程为写访问而打开该IPC对象,那么用户写权限位必须设置。)

  3. 在当前进程的有效组ID或它的某个辅助组ID等于该IPC对象的组ID的前提下,若相应的组访问权限位已设置,那就允许访问,否则拒绝访问。

  4. 若相应的其他用户访间权限位已设置,那就允许访问,否则拒绝访问。

  • 这4个步骤是按所列的顺序尝试的。因此,如果当前进程拥有该IPC对象,那么访问权的授予与拒绝只依赖于用户访问权限(组访问权限绝不会考虑)。

    • 若当前进程不拥有该IPC对象,但它属于某个合适的组,那么访问权的授予与拒绝只依赖于组访问权限(其他用户访问权限绝不会考虑)。

二、System V IPC

1.概述

三种类型的IPC和称为"System V IPV":

  1. System V消息队列。

  2. System V信号量。

  3. System V共享内存区。

下图显示System V IPC函数:
在这里插入图片描述

2.key_t键和ftok函数

三种类型的System V IPC使用key_t值作为它们的名字。头文件<sys/types.h>key_t这个数据类型定义为 一个整数,通常至少32位的整数。这些整数值通常是由ftok函数赋予的。

函数ftok把已存在的路径名和整数标识符转换成一 个key_t值,称为IPC键。

//函数从pathname导出的信息与id的低序8位组合成一个整数IPC键。
#include<sys/ipc.h>
key_t ftok(const char *pathname,int fd);
  1. 该函数假定对于使用System V IPC的某个给定应用来说,客户和服务器同意使用对该应用有一 定意义的pathnam e

  2. pathname可以是服务器守护程序的路径名、 服务器使用的某个公共数据文件的路径名或者系统上的某个其他路径名。

  3. 若客户和服务器之间只需单个IPC通道,那么可以使用譬如说值为1的id。

  4. 若需要多个IPC通道,譬如说从客户到服务器一个通道,从服务器到客户又一 个通道,那么作为一 个例子,一 个通道可使用值为1的id, 另一个通道可使用值为2的id 。

  5. 客户和服务器 一 旦在pathname和id上达成一致,双方就都能调用ftok函数把pathnameid转换成同一个IPC键。

ftok的典型实现调用stat函数,然后组合以下三个值:

  1. pathname所在的文件系统的信息(stat结构的st_dev成员)。

  2. 该文件在本文件系统内的索引节点号(stat结构的st_ino成员)。

  3. id的低序8位(不能为0)。

  • 三个值的组合通常会产生32位键。不能保证两个不同的路径名与同一个id的组合产生不同的键,因为上面所列三个条目(文件系统标识符、索引节点、id)中的信息位数可能大于一个整数的信息位数。

    • pathname不存在,或者对于调用进程不可访问,ftok返回-1。

      • 路径名用于产生键的文件不能是在服务器存活期间由服务器反复创建并删除的文件,因为该文件每次创建时由系统赋予的索引节点号很可能不 一 样,于是对下一 个调用者来说,由ftok返回的键也可能不同。

例:下列程序取一个作为命令行参数的路径名,调用stat,调用ftok,然后输出stat结构的st_dev和st_ino成员以及得出的IPC键。十六进制输出,从两个值以及id值0x57看出IPC键如何构造的。

int main(int argc,char **argv)
{struct stat stat;if(argc!=2)err_quit("usage:ftok<pathname>");stat[argv[1],&stat);printf("st_dev:%lx,st_ino:%lx,key:%x\n",(u_long)stat.st_dev,(u_long)stat.st_ino,ftok(argv[1],0x57))exit(0);
}

在这里插入图片描述
id在IPC键的高序8位,st_dev的低序12位IPC在键的接下来12位,st_ino的低序12位则在IPC键的低序12位。

3.ipc_perm结构

内核每个IPC对象维护一个信息结构,其内容跟内核给文件维护的信息类似。

<sys/ipc.h>
struct ipc_perm{uid_t 	uid;gid_t 	gid;uid_t 	cuid;gid_t 	cgid;mode_t	mode;ulong_t	seq;key_t 	key;
};

4.创建与打开IPC通道

创建或打开一个IPC对象的三个get_XXX函数的第一个参数为key是类型为key_t的IPC键,返回值identifier是一个整数标识符。该标识符不同于ftok函数的id参数,key有两种选择:

  1. 调用ftok,给它传递pathname和id。
  2. 指定key为IPC_PRIBATE,保证创建一个新的、唯一的IPC对象。

在这里插入图片描述
所有三个get_XXX函数都有一个名为oflag的参数,指定IPC对象的读写权限位(ipc_perm结构的mode成员),并选择是创建一个新的IPC对象还是访问一个已存在的IPC对象.这种选择的规则如下:

  1. 指定key为IPC_PRIVATE能保证创建一个唯一的!PC对象。没有一对id和pathname的组合会导致ftok产生IPC_PRIVATE这个键值。

  2. 设置oflag参数的IPC_CREAT位但不设置它的IPC_EXCL位时,若所指定键的IPC对象不存在,那就创建一个新的对象,否则返回该对象。

  3. 同时设置oflag的IPC_CREAT和IPC_EXCL位时,若所指定键的IPC对象不存在,那就创建一个新的对象,否则返回EEXIST错误,因为该对象已存在。

  • 对IPC对象来说,IPC_CREAT和IPC_EXCL的组合跟open函数的O_CREAT和O_EXCL的组合类似。

    • 设置IPC_EXCL位但不设置IPC_CREAT位是没有意义的。

下图展示打开IPC对象的逻辑图:

在这里插入图片描述
IPC对象的逻辑图l另一种形式:
在这里插入图片描述

  1. 中间只有IPC_CREAT而没有IPC_EXCL标志的那一行,得不到一个指示以判别是创建了一个新对象,还是在引用一个已存在的对象。

  2. 大多数应用程序中,由服务器创建IPC对象并指定IPC_CREAT标志(如果它不关心该对象是否存在)或IPC_CREAT I IPC_EXCL标志(如果它需要检查该对象是否已经存在)。

  3. 客户则不指定其中任何一个标志(前提服务器已经创建了对象)。

5.IPC权限

每当使用某个get_XXX函数(指定IPC_CREAT标志)创建一个新的IPC对象时,以下信息就保存到该对象的ipc_perm结构中。

  1. oflag参数中某些位初始化ipc_perm结构的mode成员。下图展示System V三种不同的IPC机制的权限位(>>3右移3位)。在这里插入图片描述

  2. cuid和cgid成员分别设置为调用进程的有效用户ID和有效组ID。这两个成员合称为创建者ID。

  3. ipc_perm结构的uid和gid成员也分别设置为调用进程的有效用户ID和有效组ID。这两个成员合称为属主ID 。

尽管一个进程可通过调用相应IPC机制ctlXXX函数(所用命令为IPC_SET)修改属主ID,创建者ID却从不改变。三个ctlXXX函数还允许一个进程修改某个IPC对象的mode成员。

每当有一个进程访问某个IPC对象时,IPC就执行两级检查,该IPC对象被打开时(getXXX函数)执行 一 次,以后每次使用该对象时执行一 次。

  1. 每当有进程以某个getXXX函数 建立访问某个已存在IPC 对象的通道时,IPC 就执行一次初始检查,验证调用者的oflag参数没有指定不在该对象ipc_perm结构mode成员中的任何访问位。

     	1. 一个服务器进程可以把它的输入消息队列的mode成员设置成关掉组成员读和其他用户读这两个权限位。2. 任何进程调用针对该消息队列的msgget函数时,如果所指定的oflag参数包含这两位,那么该函数都将返回 一 个错误。3. 然而由`getXXX` 函数完成的这种测试并没有多大用处,它隐含假定调用者知道自己属于哪个权限范畴一用户组成员或其他用户。4. 若创建者特意关掉了某些权限位,而调用者却指定了这些位,那么getXXX函数将检测出这个错误。5. 然而任何进程都能够完全绕过这种检查,其办法是在得知该IPC对象已存在后,简单地指定 一 个值为0的oflag参数即可。
    
  2. 每次IPC操作都对使用该操作的进程执行一次权限测试。例:每当有一个进程试图使用msgsnd函数往某个消息队列放置 一 个消息时,msgsnd函数将以下面所列的顺序执行 (多个)测试。一旦某个测试赋予了访问权,其后的测试就不再执行。

     	1. 超级用户总是赋予访问权。2. 若当前进程的有效用户lD等于该IPC对象的u`id值或cuid值`,而且**相应的访问位**在该IPC对象的`mode`成员中是打开的,那么赋予访问权。(相应的访问位:若调用者想要在该IPC对象上执行 一 个读操作 ,那么读位必须设置,如果想要执行 一 个写操作,那么写位必须设置)。3. 若当前进程的有效组ID等于该IPC对象的`gid值或cgid值`,而且相应的访问位在该IPC对象的`mode`成员中是打开的,那么赋予访问权。4. 如果上面的测试没有一个为真那么相应的 “其他用户” 访问位在该IPC对象的mode成员中必须是打开的才能赋予访问权。
    
6.标识符重用
  1. ipc_perm结构含有seq的变量,表示槽位使用情况序列号。该变量是由内核为系统中每个潜在的IPC对象维护的计数器。每当删除一 个IPC对象时,内核就递增相应的槽位号,若溢出则循环回0。

  2. System V IPC标识符是系统范围的,而不是特定于进程的。

  3. 由于某个行为不端的进程可能尝试从另外某个应用的消息队列读消息,办法是尝试不同的小整数标识符,以期待找出一个当前在使用的允许大家读访问的消息队列。要是这些标识符取值是小整数,那么找到一个有效标识符的可能性为1:50。

  4. 避免这种问题,把IPC机制的标识符可能范围扩大到包含所有整数,而不是小整数。实现:每次重用一个IPC表项,把返回给调用进程的标识符增加一个IPC表项数。

递增槽位使用情况序列号的另 一 个原 因是:避免短时间内重用System VIP 示识符。这有助与确保过早终止的服务器重新启动后不会重用标识符。

例:返回前10标识符值。

int main(int argc,char **argv)
{int i,msqid;for(i=0;i<10;i++){msqid = msgget(IPC_PRIVATE,SVMSG_MODE|IPC_CREAT);printf("msqid=%d\n",msqid);msgctl(msqid,IPC_RMID,NULL);}exit(0)}
7.ipcs和ipcrm程序

System V IPC的三种类型不是以文件系统中的路径名标识的,因此使用标准的ls和rm程序无法看到它们,也无法删除它们。但实现了这些类型IPC的任何系统都提供两个特殊的程序:

  1. ipcs输出有关System VIPC特性的各种信息。

  2. ipcrm则删除一个SystemV消息队列、信号量集或共享内存区。

8.内核限制
  1. System V IPC的多数实现有内在的内核限制,例如消息队列的最大数目、每个信号量集的最大信号量数,等等。

  2. 这些对象的大小被内核限制得往往太小,因为其中许多限制起源于在某个小地址空间系统完成的最初实现。但是多数系统允许管理员部分或完全修改这些默认限制。

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

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

相关文章

Redux的基本使用过程详解

文章目录Redux的使用过程Redux测试项目的搭建Redux的基本使用步骤Redux目录的结构划分React的三大原则Redux的使用过程 Redux测试项目的搭建 1.创建一个新的项目文件夹:learn-redux # 执行初始化操作 npm init -y或yarn init -y # 安装redux:npm install redux --save或yarn …

自定义View 布局过程(Layout)

目录一、作用二、layout过程详解2.1单一View的layout过程具体使用具体流程源码分析总结2.2ViewGroup的layout过程具体使用具体流程源码分析总结三、细节问题&#xff1a;getWidth() &#xff08; getHeight()&#xff09;与 getMeasuredWidth() &#xff08;getMeasuredHeight(…

Java高级——编译JDK

编译JDKJDK是什么&#xff1f;编译环境搭建JDK下载编译参数编译在IDE中调试源码JDK是什么&#xff1f; Java Development Kit&#xff0c;用于执行和开发java程序 编译环境搭建 本文采用Ubantu 18.04 执行以下命令安装依赖 apt-get install build-essential apt-get instal…

Transformer

参考 https://www.ylkz.life/deeplearning/p12158901/ https://zhuanlan.zhihu.com/p/396221959 模型结构 Input Embedding 将文本中词汇的数字表示转变为向量表示, 希望得到其在高维空间中的特征表示向量。 # 导入必备的工具包 import torch import torch.nn as nn import …

Qt5开发从入门到精通——第九篇一节( Qt5 文件及磁盘处理—— 读写文本文件)

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 欢迎小伙伴的点评✨✨&#xff0c;相互学习c/c应用开发。&#x1f373;&#x1f373;&#x1f373; 博主&#x1f9d1;&#x1f9d1; 本着开源的精神交流Qt开发的经验、将持续更新续章&#xff0c;为社区贡献博主自身的开源精…

esp32-C3 CAN接口使用

esp32-C3 CAN接口使用功能概述CAN协议关注点接收过滤器单过滤器模式双过滤器模式关键函数说明配置和安装驱动获取TWAI状态信息发送/接收消息使用示例CAN控制器自回环测试CAN收发带过滤测试功能概述 ESP32-C3具有1个CAN控制器支持以下特性&#xff1a; 兼容ISO 11898-1协议(CA…

伟大的micropython smartconfig 配网它来了!!!

我这其实只是实验和搬运&#xff0c;还是感谢伟大的walkline群主&#xff0c;他弄好的&#xff0c;我只是负责搬运发布给新手看。 之前一大堆人问我配网的事儿&#xff0c;输入下wifi名称密码这么麻烦吗&#xff0c;好吧&#xff0c;有求必应&#xff0c;之前的配网是通过ap模式…

PICO高管专访:关于PICO 4硬件、内容、定价、海外布局的一切解答

PICO 4昨天正式在国内发布&#xff0c;简单来说这是一款相对均衡的VR一体机&#xff0c;在硬件素质、内容生态建设上都可圈可点&#xff0c;对于国内还未入手VR的朋友们来说是非常好的选择。相关阅读&#xff1a;《PICO 4评测&#xff1a;Pancake光学新标杆&#xff0c;VR娱乐V…

20【访问者设计模式】

文章目录二十、访问者设计模式20.1 访问者设计模式简介20.1.1 访问者设计模式概述20.1.2 访问者设计模式的UML类图20.2 访问者设计模式的实现20.3 访问者设计模式的优缺点二十、访问者设计模式 20.1 访问者设计模式简介 20.1.1 访问者设计模式概述 访问者设计模式&#xff0…

计算机网络基础 VLSM----可变长子网掩码;CIDR技术----无类域间路由;

VLSM----可变长子网掩码&#xff1a; 概述&#xff1a; 通过网络位向主机位借位的方式&#xff0c;延长子网掩码&#xff0c;从而达到将一个大网络划分为多个小网络&#xff1b;借出的位数称之为子网位&#xff0c;决定了能划分网络的个数。 优点&#xff1a; 更高效的利用…

记一次导入下载好的源码工程到本地工程异常解决方案

今天在学习okhttp相关视频时&#xff0c;安装视频的操作在自己的工程中引入三方的模块&#xff0c;但是发现引入后和预期的不一致。不一致指的是&#xff0c;视频中以module方式引入sample-okhttp并解决冲突后&#xff0c;sample-okhttp能够被android stuidio识别为applicayion…

Style样式设置器

构成Style最重要的两种元素&#xff1a; Setter类帮助我们设置控件的静态外观风格 Trigger类则帮助我们设置控件的行为风格。 Setter,设置器&#xff0c;我们给属性赋值的时候一般都采用“属 性名属性值”的形式 上面的例子中针对TextBlock的Style&#xff0c;Style中使用 若…

解决csdn强制关注博主才能阅读文章

问题 有的时候查阅资料的时候,关注博主并不是很方便,查csdn会出现下面的提示解决办法 打开控制台输入以下代码: var article_content=document.getElementById("article_content"); article_content.removeAttribute("style");var follow_text=document…

深入理解计算机系统——第七章 Linking

深入理解计算机系统——第七章 Linking7.1 Compiler Drivers7.2 Static Linking7.3 Object Files7.4 Relocatable Object Files7.5 Symbols and Symbol Tables7.6 Symbol Resolution7.6.1 How Linkers Resolve Duplicate Symbol Names7.6.2 Linking with Static Libraries7.6.3…

人体神经元结构示意图,神经细胞内部结构图

人体神经结构图&#xff1f;&#xff1f;&#xff1f;&#xff1f; 谷歌人工智能写作项目&#xff1a;神经网络伪原创 下图为神经系统的结构示意图&#xff0c;请根据图回答&#xff1a; &#xff08;1&#xff09;构成神经系统的结构、功能单位是神经元&#xff0c;图中E部分…

19【迭代器设计模式】

文章目录十九、迭代器设计模式19.1 迭代器设计模式简介19.1.1 迭代器设计模式概述19.1.2 迭代器设计模式的UML类图19.2 迭代器设计模式的实现19.3 迭代器设计模式的优缺点十九、迭代器设计模式 19.1 迭代器设计模式简介 19.1.1 迭代器设计模式概述 迭代器设计模式&#xff0…

DeFi借贷重新洗牌 透过协议变化能找到哪些新趋势?

在过去的几个月里&#xff0c;DeFi 借贷赛道产生了重大变化&#xff0c;1kx 研究员 Mikey 0x 对此场域重新进行梳理&#xff0c;BlockBeats 对其整理翻译如下&#xff1a; 本文内容将包括对新借贷协议的介绍、核心数据统计以及发展趋势&#xff0c;也许可以让我们大致把握下一…

Python3操作MongoDB数据库

Python3操作MongoDB数据库 文章目录Python3操作MongoDB数据库0. 写在前面1. 安装开源驱动库pymongo2. 参考0. 写在前面 Linux&#xff1a;Ubuntu Kylin 16.04MongoDB&#xff1a;MongoDB3.2.7Python&#xff1a;Anaconda With Python3.7 1. 安装开源驱动库pymongo pymongo驱动…

公众号题库搜题对接(免费接口)

公众号题库搜题对接(免费接口) 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&a…

用神经网络表示与逻辑,神经网络实现逻辑运算

数据挖掘中的神经网络和模糊逻辑的概念是啥&#xff1f; 【神经网络】人工神经网络&#xff08;Artificial Neural Networks&#xff0c;简写为ANNs&#xff09;也简称为神经网络&#xff08;NNs&#xff09;或称作连接模型&#xff08;Connection Model&#xff09;&#xff…