当前位置: 首页 > news >正文

System V通信机制

IPC对象概述

IPC对象消息队列共享内存信号量
特点多对多共享数据具备阻塞的全局变量

在这里插入图片描述

设置流程

  1. 获取IPC对象key
  2. xxxget//获取对象ID值
  3. xxxctl//操作函数
  4. 相对独立的操作函数

IPC相关bash命令

ipcs [-参数]
>-a:显示所有 IPC 设施(默认选项)。
>-q:仅显示消息队列。
>-m:仅显示共享内存段。
>-s:仅显示信号量。
>-l:显示 IPC 资源的系统限制。
>-u:显示 IPC 设施的汇总信息。
>-p:显示与 IPC 设施相关的进程 ID。
>-t:显示时间信息,如上次操作时间。
>-c:显示创建者的用户和组信息。
>-b:显示 IPC 设施的权限和大小信息。ipcrm -[参数]#在bash中删除IPC对象
> -m, --shmem-id <id>        remove shared memory segment by id
> -M, --shmem-key <key>      remove shared memory segment by key
> -q, --queue-id <id>        remove message queue by id
> -Q, --queue-key <key>      remove message queue by key
> -s, --semaphore-id <id>    remove semaphore by id
> -S, --semaphore-key <key>  remove semaphore by key
> -a, --all[=shm|msg|sem]    remove all (in the specified category)
> -v, --verbose              explain what is being done
> -h, --help                 display this help
> -V, --version              display version

消息队列

在这里插入图片描述

1.创建key

函数原型key_t ftok(const char *pathname, int proj_id);
头文件#include <sys/ipc.h>
参数pathname:指向一个已存在文件的路径字符串,key:一个 8 位的项目标识符(范围 0-255)
返回值成功返回key_t类型,失败返回*-1*

2.创建对象

函数原型int msgget(key_t key, int msgflg);
头文件#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
参数key:由 ftok msgflg:标志位,用于指定队列的权限和创建行为
返回值成功时返回消息队列的标识符(非负整数)。失败时返回 -1
msgflg
IPC_CREATIPC_CREAT:如果队列不存在,则创建。
IPC_EXCL与 IPC_CREAT 一起使用,确保队列不存在时创建,否则返回错误。
权限模式IPC_CREAT|0666:在创建时同时复制权限

3.进行发送

函数原型int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
头文件#include <sys/msg.h>
参数msqid:消息队列标识符,由 msgget 函数返回。msgp:指向消息缓冲区的指针,缓冲区需包含消息类型和消息内容。msgsz:消息正文的大小(以字节为单位),不包括消息类型字段;msgflg:控制标志,通常为 0(阻塞模式)或 IPC_NOWAIT(非阻塞模式)。
返回值成功时返回 0,失败时返回 -1 并设置 errno。
msgflag
IPC_NOWAIT非阻塞模式
0进行阻塞

在创建根据手册描述需要创建一个包含正文,和类型的结构体

struct msgbuf {long mtype;     // 消息类型,必须为正整数char mtext[1];  // 消息正文,实际使用时需自定义长度
};

示例

typedef struct msgbuf
{long mtype;       /* message type, must be > 0 */char mtext[1024];    /* message data */
}msgbuf;int main(void)
{key_t key = ftok(".", 123);//在当前路径下创建生成一个"钥匙"int mag_id = msgget(key, IPC_CREAT | 0664);//创建一个新的消息队列msgbuf my_msbuf;my_msbuf.mtype = 100;memset(my_msbuf.mtext, 0, sizeof(my_msbuf.mtext));scanf("%s", my_msbuf.mtext);msgsnd(mag_id, &my_msbuf, strlen(my_msbuf.mtext), 0);//进行阻塞的发送信息return 0;
}

运行结果
在这里插入图片描述

4.进行接收

函数原型int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
头文件#include <sys/msg.h>
参数msqid:消息队列标识符,由 msgget 创建。msgp:通常是一个结构体,包含消息类型和消息正文。msgsz:消息正文的大小msgtyp:指定接收的消息类型;msgflg:控制行为的标志位
返回值成功时返回实际接收的消息正文的字节数。失败时返回 -1,并设置 errno。
msgflag
IPC_NOWAIT如果没有符合条件的消息,立即返回错误(不阻塞)
MSG_NOERROR如果消息正文超过 msgsz,截断消息而不报错。
0进行阻塞

示例

int main(void)
{key_t key = ftok(".", 123);//在当前路径下创建生成一个"钥匙"int mag_id = msgget(key, IPC_CREAT|0664);//创建一个新的消息队列msgbuf my_msbuf;my_msbuf.mtype = 200;while (1){memset(my_msbuf.mtext, 0, sizeof(my_msbuf.mtext));msgrcv(mag_id, &my_msbuf, sizeof(my_msbuf.mtext), 100, MSG_NOERROR);//进行阻塞的发送信息printf("2接收到程序:%s\n", my_msbuf.mtext);}
}

运行结果
在这里插入图片描述

5.操作消息队列

函数原型int msgctl(int msqid, int cmd, struct msqid_ds *buf);
头文件#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
参数msqid:消息队列的标识符,由 msgget 函数创建或获取。cmd:控制命令;buf:指向 struct msqid_ds 的指针,用于存储或设置消息队列的属性。
返回值成功时返回 0。失败时返回 -1,并设置 errno 以指示错误类型。

属性信息结构体struct msqid_ds

struct msqid_ds {struct ipc_perm msg_perm;  // 权限信息time_t msg_stime;          // 最后发送消息的时间time_t msg_rtime;          // 最后接收消息的时间time_t msg_ctime;          // 最后修改时间unsigned long __msg_cbytes; // 当前队列中的字节数msgqnum_t msg_qnum;        // 当前队列中的消息数msglen_t msg_qbytes;       // 队列的最大字节数pid_t msg_lspid;           // 最后发送消息的进程 PIDpid_t msg_lrpid;           // 最后接收消息的进程 PID
};

常用命令

cmd
IPC_STAT获取消息队列的属性,存储到 buf 指向的结构体中
IPC_SET设置消息队列的属性,从 buf 指向的结构体中读取
IPC_RMID立即删除消息队列,忽略 buf 参数

示例

int main(void)
{key_t key = ftok(".", 123);//在当前路径下创建生成一个"钥匙"int mag_id = msgget(key, IPC_CREAT | 0664);//创建一个新的消息队列msgbuf my_msbuf;my_msbuf.mtype = 100;struct msqid_ds msginfo;msgctl(mag_id, IPC_STAT,&msginfo);printf("信息数量:%lu\n", msginfo.msg_qnum);return 0;
}

运行结果
在这里插入图片描述

消息队列是流操作


共享内存

在这里插入图片描述

1.创建创建key

创建key与消息队列相同,这里就不过多赘述

*2.创建shareMemoryID

函数原型int shmget(key_t key, size_t size, int shmflg);
头文件#include <sys/ipc.h> #include <sys/shm.h>
参数key:共享内存段的键值,通常由 ftok 生成或直接使用 IPC_PRIVATE。size:共享内存段的大小,通常是4096的倍数。如果是获取已存在的共享内存,此参数可设为 0。shmflg:权限标志
返回值成功时返回共享内存段的标识符(非负整数)。失败时返回 -1,并设置 errno 表示错误原因。

shmflg

shmflg
IPC_CREAT创建,可以与限权相或进行设置
IPC_EXCL确保在创建新的 IPC 资源(如共享内存、消息队列或信号量)时,如果该资源已存在,则创建操作会失败。

3.映射内存

函数原型void *shmat(int shmid, const void *shmaddr, int shmflg);
头文件#include <sys/shm.h>
参数shmid:共享内存标识符,由 shmget 调用返回;shmaddr:指定共享内存附加到进程地址空间的位置。通常设为 NULL,由系统自动选择地址。shmflg:附加标志,例如 SHM_RDONLY 表示只读访问。
返回值shmat 返回共享内存附加到进程地址空间的起始地址。失败时,返回 (void *)-1,并设置 errno 以指示错误原因。

shmflg

shmflg
0默认,代表共享内存可读可写。
SHM_RDONLY代表共享内存只读。

示例

int main(void)
{key_t key = ftok(".", 1);//在当前路径下创建生成一个"钥匙"if(key == -1){perror("ftok sailed\n");}int shm_ID = shmget(key, 4096, IPC_CREAT|0664);if (shm_ID == -1) {perror("shmget failed\n");exit(1);}int shmdt(const void *shmaddr);char * add = shmat(shm_ID, NULL, 0);sprintf(add, "1234");printf("%s", add+1);return 0;
}

执行结果
在这里插入图片描述

操作

函数原型int shmctl(int shmid, int cmd, struct shmid_ds *buf);
头文件#include <sys/ipc.h> #include <sys/shm.h>
参数shmid:指定的共享内存的ID;cmd:一些命令字;buf:用来存放共享内存信息的结构体
返回值失败返回-1

cmd参数说明

cmd
IPC_STAT将共享内存的当前状态信息复制到 buf 指向的 shmid_ds 结构中。调用者需具备读权限。
IPC_SET通过 buf 修改共享内存的权限、所有者或时间戳等字段。仅超级用户或有效用户 ID 与共享内存所有者/创建者匹配的用户可执行。
IPC_RMID标记共享内存段为待销毁状态。实际销毁会在最后一个附加进程分离后发生。此操作需超级用户或有效用户 ID 匹配所有者/创建者。
http://www.dtcms.com/a/332485.html

相关文章:

  • 博弈论06——PPAD复杂度问题
  • 47.分布式事务理论
  • demo 通讯录 + 城市选择器 (字母索引左右联动 ListItemGroup+AlphabetIndexer)笔记
  • 2025最新:如何禁止指定软件联网?
  • 字符LCD显示模块是什么?
  • sqli-labs通关笔记-第50关 GET数值型order by堆叠注入(手工注入+脚本注入两种方法)
  • 智能工厂生产监控大屏-vue纯前端静态页面练习
  • [git] 当GitHub宕机时,我们如何协作?| github同步gitee的部署方法
  • 通俗易懂理解盲超分
  • 「iOS」————APP启动优化
  • 中年海尔,是时候押注新方向了
  • 笔试——Day39
  • Lecture 10: Concurrency 3
  • Midjourney绘画创作入门操作
  • 项目管理工具
  • 数据结构初阶:排序算法(二)交换排序
  • 第5节 循环神经网络 RNN(Recurrent Neural Network)
  • 基于多模型的零售销售预测实战指南
  • day31 UDP通信
  • 数据结构初阶(15)排序算法—交换排序(快速排序)(动图演示)
  • Android 欧盟网络安全EN18031 要求对应的基本表格填写
  • 【CUDA 编程思想】FusedQKVProj-分组量化矩阵乘法高效实现全流程解析
  • 思考:高速场景的行星轮混动效率如何理解
  • 读《精益数据分析》:黏性(Stickiness)—— 验证解决方案是否留住用户
  • STM32L051同时处理Alarm A和Alarm B中断
  • 【机器人-基础知识】ROS1和ROS2对比
  • 一周学会Matplotlib3 Python 数据可视化-绘制误差条形图
  • 自定义View学习记录之 滚动抽奖单片
  • 前端性能优化工具Performance面板实战指南
  • 为什么 /deep/ 现在不推荐使用?