网站推广营销策划方案文大侠seo博客
目录
共享内存概述
共享内存函数
(1)shmget函数
功能概述
函数原型
参数解释
返回值
示例
结果
(2)shmat函数
功能概述
函数原型
参数解释
返回值
(3)shmdt函数
功能概述
函数原型
参数解释
返回值
示例1(所有函数结合总示例)
结果
示例2(内存偏移存取数据)
结果
共享内存概述
共享内存在进程间传输数据的效率极高。
概念:在物理内存中开辟一块区域,让多个进程能将其映射到各自虚拟地址空间,实现对同一块内存的共享访问。
原理:先由进程创建共享内存获标识符,其他进程再将其映射到自身地址空间,然后进程就能像访问普通内存一样对其进行读写操作。
优点:数据传输快,因为无需像其他通信方式那样进行数据复制;能支持大量数据传输,适合对大块数据的频繁访问。
缺点:需进程自行处理同步和互斥问题,以避免数据冲突;使用不当易引发程序错误和内存泄漏,且不支持跨机器的进程通信。
应用场景:常用于对通信速度要求高的场景,如实时数据处理系统、数据库系统中的缓冲区管理等。
共享内存函数
(1)shmget函数
功能概述
shmget
是一个用于创建或获取共享内存段的系统调用,主要用于在类 Unix 系统(如 Linux)中实现进程间通信(IPC)
函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);
参数解释
key
:用于标识共享内存段的键值。它可以是通过ftok
函数生成的唯一键值,也可以是IPC_PRIVATE
。若为IPC_PRIVATE
,则会创建一个新的、私有的共享内存段,该共享内存段只能由创建它的进程及其子进程访问。
size
:指定要创建或获取的共享内存段的大小,以字节为单位。若要创建新的共享内存段,此参数必须大于 0。
shmflg
:一组标志位,用于控制共享内存段的创建和访问权限。常见标志如下:
IPC_CREAT
:若指定的共享内存段不存在,则创建它。
IPC_EXCL
:与IPC_CREAT
一起使用时,若共享内存段已存在,函数会失败并返回 -1。权限标志:如0666
,用于设置共享内存段的访问权限,类似于文件的权限设置。
返回值
若调用成功,返回一个非负整数,即共享内存段的标识符(shmid
),后续的共享内存操作会使用这个标识符。
若失败,返回 -1,并设置 errno
来指示错误类型。
示例
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>using namespace std;typedef struct student
{char stuid[20];char stuname[20];
}STU;int main()
{int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);if (shmid < 0){perror("shmget error");}return 0;
}
结果
下面第二个就是我们创建的共享内存
(2)shmat函数
功能概述
shmat
函数是类 Unix 系统(如 Linux)中用于将共享内存段附加到调用进程的地址空间的系统调用,通过它进程可以像访问自身内存一样访问共享内存段。
函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);
参数解释
shmid
:这是由shmget
函数返回的共享内存段标识符,用于指定要附加的共享内存段。
shmaddr
:它指定共享内存段要附加到的进程地址空间的地址。一般可设置为NULL
,让系统自动选择合适的地址进行附加。
shmflg
:这是一组标志位,用于控制附加操作的行为,常见标志如下:
SHM_RDONLY
:以只读模式附加共享内存段,即进程只能读取共享内存中的数据,不能进行写入操作。
0
:以读写模式附加共享内存段。
返回值
若调用成功,返回指向共享内存段在进程地址空间中起始地址的指针,后续进程可通过该指针访问共享内存段。
若失败,返回 (void *)-1
,并设置 errno
来指示错误类型。
(3)shmdt函数
功能概述
shmdt
函数在类 Unix 系统里用于将共享内存段从调用进程的地址空间分离。分离后,进程就无法再通过之前附加时得到的指针来访问该共享内存段,但共享内存段本身并不会被删除,其他仍附加了该共享内存段的进程依旧可以访问它。
函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>int shmdt(const void *shmaddr);
参数解释
shmaddr
:这是一个指向共享内存段在进程地址空间中起始地址的指针,该指针是之前调用 shmat
函数时返回的。
返回值
若调用成功,返回 0
。
若失败,返回 -1
,同时设置 errno
以指示错误类型。
示例1(所有函数结合总示例)
Amain.cpp发送数据
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>using namespace std;typedef struct student
{char stuid[20];char stuname[20];
}STU;int main()
{void* shmaddr = NULL;int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);if (shmid < 0){perror("shmget error");}else{// 链接共享内存shmaddr = shmat(shmid, NULL, 0);// 共享内存写入数据STU stu = { "2019211001", "zhangsan" };memcpy(shmaddr, &stu, sizeof(STU));// 断开链接共享内存shmdt(shmaddr);}return 0;
}
Bmain.cpp接收数据
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>using namespace std;typedef struct student
{char stuid[20];char stuname[20];
}STU;int main()
{void* shmaddr = NULL;int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);if (shmid < 0){perror("shmget error");}else{// 链接共享内存shmaddr = shmat(shmid, NULL, 0);// 共享内存取数据STU stu = { 0 };memcpy(&stu, shmaddr, sizeof(STU));cout << "学号:" << stu.stuid << endl;cout << "姓名:" << stu.stuname << endl;memset(shmaddr, 0, sizeof(STU)); // 清空共享内存数据// 断开链接共享内存shmdt(shmaddr);}return 0;
}
注:因为是对内存直接操作,所以在取完数据之后记得清空内存
结果
示例2(内存偏移存取数据)
Amain.cpp
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>using namespace std;typedef struct student
{char stuid[20];char stuname[20];
}STU;int main()
{void* shmaddr = NULL;int shmid = shmget((key_t)1002, sizeof(STU)*3, IPC_CREAT | 0777);if (shmid < 0){perror("shmget error");}else{// 链接共享内存shmaddr = shmat(shmid, NULL, 0);// 共享内存写入数据STU stu = { 0 };for (int i = 1; i < 4; i++){sprintf(stu.stuid, "%d", i);sprintf(stu.stuname, "name%d", i);memcpy(shmaddr + sizeof(STU) * (i - 1), &stu, sizeof(STU));}// 断开链接共享内存shmdt(shmaddr);}return 0;
}
Bmain.cpp
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>using namespace std;typedef struct student
{char stuid[20];char stuname[20];
}STU;int main()
{void* shmaddr = NULL;int shmid = shmget((key_t)1002, sizeof(STU)*3, IPC_CREAT | 0777);if (shmid < 0){perror("shmget error");}else{// 链接共享内存shmaddr = shmat(shmid, NULL, 0);// 共享内存取数据STU stu = { 0 };for (int i = 1; i < 4; i++){memcpy(&stu, shmaddr + sizeof(STU) * (i - 1), sizeof(STU));cout << "次数" << i << "学号:" << stu.stuid << endl;cout << "次数" << i << "姓名:" << stu.stuname << endl;}memset(shmaddr, 0, sizeof(STU)); // 清空共享内存数据// 断开链接共享内存shmdt(shmaddr);}return 0;
}