进程间通信——共享内存
创始人
2024-05-07 03:51:11
0

目录

1 概念

 

2 操作流程

fork(获取key值)

shmget(申请对象)

shmat(内存映射)

读写共享内存:类似堆区内存的直接读写

shmdt(解除映射)

shmctl(删除对象)

范例:


 

1 概念

共享内存是进程间通信中最简单最高效的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。

 

2 操作流程

1     获取K值   ftok
2     申请对象  shmget
3     内存映射  shmat
4     读写共享内存
5    解除映射  shmdt
6    删除对象  shmctl

fork(获取key值)

key_t ftok(const char *pathname, int proj_id);

功能:

通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值。
参数:

pathname 路径 ,任意路径,只要不会被删除即可。但是读写端路径指向必须一致proj_id  代号,整形的数据,一般用ASCII码的单字符表示

返回值:

成功 返回唯一键值
失败  -1;

shmget(申请对象)

int shmget(key_t key, size_t size, int shmflg);

功能:
创建共享内存
参数:
key:键值
size:共享内存大小
shmflg:
IPC_CREAT    创建 (低9个bits表示用户,同组用户,其他人的权限)
IPC_EXCL    检测是否存在
返回值:
成功返回共享内存ID
失败返回-1  

shmat(内存映射)

void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:

将指定shmid对应的共享内存映射到本地内存。
参数:

shmid 要映射的共享内存id
shmaddr 本地可用的地址,如果不确定则用NULL,表示由系统自动分配。
shmflg  :操作权限
SHM_RDONLY,只读
!SHM_RDONLY 读写
返回值:

成功 返回映射的地址,一般等于shmaddr
失败 (void*) -1 

读写共享内存:类似堆区内存的直接读写

shmdt(解除映射)

int shmdt(const void *shmaddr);

功能

将本地内存与共享内存断开映射关系。
参数:

shmaddr 要断开的映射地址。
返回值

成功  0
失败  -1; 

shmctl(删除对象)

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能

修改共享内存属性,也可以删除指定的共享内存对象。
参数:

shmid 要删除的共享内存对象
cmd 
        IPC_STAT            获得信息
        IPC_SET              设置权限
        IPC_RMID            删除 
buff 
NULL 表示只删除对象。
返回值:

成功 0 

范例:

编写两个进程任务利用共享内存通信,一个负责从终端接写入共享内存中,另一个负责打印共享内存数据,直到输入quit两个进程任务结束

进程1发送

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include int main(int argc, char const *argv[])
{key_t key;printf("\33[35m\33[1mmess_t\33[0m\33[36m\33[1m开始配对...\33[0m\n");key = ftok(".",258);//获取k值-----1if(-1 == key){perror("fail to ftok");return 0;}printf("key: 0X%x\n",key);int shm_id = shmget(key,4096,IPC_CREAT | 0666);//申请对象-----2if(-1 == shm_id){perror("fail to shmget");return 0;}printf("shmID: %d\n",shm_id);void *pmem = shmat(shm_id,NULL,!SHM_RDONLY);//内存映射-----3if((void *)-1 == pmem){perror("fail to shmat");return 0;}pid_t R_pid = *(pid_t *)pmem;printf("R_pid = %d\n",R_pid);char tmpbuf[4096] = {0};printf("\33[32m\33[1mmess_t配对成功!\33[0m\n");while (1)//写共享内存-----4{printf("\33[35m\33[1mmess_t发送:\33[0m");fgets(tmpbuf,sizeof(tmpbuf),stdin);if(!strcmp("quit\n",tmpbuf))break;memcpy(pmem,tmpbuf,sizeof(tmpbuf));kill(R_pid,12);}shmdt(pmem);//解除映射-----5shmctl(shm_id,IPC_RMID,NULL);//删除对象-----6printf("BAIBAI!!!\n");kill(R_pid,10);return 0;
}

 进程2接收

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include int stat_0_1 = 1;
void handler(int arg)
{alarm(0);
}
void end(int arg)
{stat_0_1 = 0;
}
int main(int argc, char const *argv[])
{signal(SIGALRM, SIG_DFL); // 缺省默认signal(12, handler);      // 缺省默认signal(10, end);key_t key;printf("\33[31m\33[1mmess_r\33[0m\33[36m\33[1m开始配对...\33[0m\n");key = ftok(".", 258); // 获取k值-----1if (-1 == key){perror("fail to ftok");return 0;}printf("key: 0X%x\n", key);int shm_id = shmget(key, 4096, IPC_CREAT | 0666); // 申请对象-----2if (-1 == shm_id){perror("fail to shmget");return 0;}printf("shmID: %d\n", shm_id);void *pmem = shmat(shm_id, NULL, !SHM_RDONLY); // 内存映射-----3if ((void *)-1 == pmem){perror("fail to shmat");return 0;}pid_t *pid = pmem;*pid = getpid();char tmpbuf[4096] = {0};printf("\33[32m\33[1mmess_r配对成功!\33[0m\n");while (1){if (stat_0_1){pause(); // 挂起,等待信号printf("\33[31m\33[1mmess_r收到:\33[0m\33[1m%s", (char *)pmem);}else{break;}}shmdt(pmem);                    // 解除映射-----5shmctl(shm_id, IPC_RMID, NULL); // 删除对象-----6printf("BAIBAI!!!\n");return 0;
}

 运行结果

 

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...