共享内存特性
- 共享内存存在于Linux内核中,可以使数据双向流动
- 系统内核的所有进程都可共享此内存空间
- 进程可直接访问共享内存,通信速度快、效率高
- 通常用信号量来实现进程对共享内存同步访问的控制
共享内存API
- shmget——创建/打开共享内存
- shmat——将共享内存与当前进程相关联
- shmdt——将当前进程与共享内存间脱离关联
- shmctl——操控共享内存
一、shmget——创建/打开共享内存
1.原函数
表头文件
#include <sys/ipc.h>
#include <sys/shm.h>
定义函数
int shmget(key_t key, size_t size, int shmflg);
函数说明——创建/打开共享内存
key——共享内存名称(ftok()函数获取
size——开辟共享内存大小
shmflg——权限标志
返回值——成功返回共享内存的标识符。错误返回-1
2.示例
key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享内存的权限为可读可写
二、shmat——将共享内存与当前进程相关联
1.原函数
表头文件
#include <sys/types.h>
#include <sys/shm.h>
定义函数
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数说明——将共享内存与当前进程相关联
shmid——共享内存的标识符(shmget的返回值)
shmaddr——使用0(内核选择存储地址)
shmflg —— 使用0 (内存空间可读可写)
返回值——成功返回该共享内存的首地址。失败返回-1,错误代码在errno
2.示例
char *shaddr=shmat(shmid,0,0);//将共享内存与当前进程相关联
三、shmdt——将当前进程与共享内存间脱离关联
1.原函数
表头文件
#include <sys/types.h>
#include <sys/shm.h>
定义函数
int shmdt(const void *shmaddr);
函数说明——将当前进程与共享内存间脱离关联
shmaddr——shmat()的返回值
返回值——成功返回0。出错返回-1,错误代码在errno
2.示例
key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享内存的权限为可读可写
char *shaddr=shmat(shmid,0,0);//将共享内存与当前进程相关联
shmdt(shaddr);//将当前进程与共享内存间脱离关联
四、shmctl——操控共享内存
1.原函数
表头文件
#include <sys/ipc.h>
#include <sys/shm.h>
定义函数
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
函数说明——操控共享内存
shmid —— shmget的返回值
cmd —— 对共享内存的指令
buf —— 内存各种信息的结构体指针(共享内存模式和访问权限)(默认为0)
返回值——成功返回0。出错返回-1,错误代码在errno
2.参数取值
cmd参数:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
struct shmid_ds结构体默认如下:
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; /* Last change time */
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 */
...
};
3.示例
key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享内存的权限为可读可写
char *shaddr=shmat(shmid,0,0);//将共享内存与当前进程相关联
shmdt(shaddr);//将当前进程与共享内存间脱离关联
shmctl(shmid,IPC_RMID,0);//删除共享内存
共享内存通信例程
先写后读
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main()
{
key_t key;
int shmid;
char *shaddr;
key=ftok(".",'k');//键值获取
shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享内存的权限为可读可写
shaddr=shmat(shmid,0,0);//将共享内存与当前进程相关联
memset(shaddr,0,strlen(shaddr));
strcpy(shaddr,"Hello");//先向shaddr内存写数据
sleep(5);
printf("write succeed\n");
printf("read succeed:%s\n",shaddr);//后在shaddr内存读数据
shmdt(shaddr);//将当前进程与共享内存间脱离关联
shmctl(shmid,IPC_RMID,0);//删除共享内存
return 0;
}
先读后写
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int main()
{
key_t key;
int shmid;
char *shaddr;
key=ftok(".",'k');//键值获取
shmid=shmget(key,1024*4,0);//此共享内存的权限为可读可写
shaddr=shmat(shmid,0,0);//将共享内存与当前进程相关联
printf("read succeed:%s\n",shaddr);//先在shaddr内存读数据
memset(shaddr,0,strlen(shaddr));
strcpy(shaddr,"World");//后向shaddr内存写数据
sleep(5);
printf("write succeed\n");
shmdt(shaddr);//将当前进程与共享内存间脱离关联
return 0;
}
运行结果:先运行先写后读,再运行先读后写
write succeed
read succeed:World
read succeed:Hello
write succeed
喜欢的请收藏,谢谢你。星辰~念