Linux API-共享内存:shmget、shmat、shmdt、shmctl

共享内存特性

  1. 共享内存存在于Linux内核中,可以使数据双向流动
  2. 系统内核的所有进程都可共享此内存空间
  3. 进程可直接访问共享内存,通信速度快、效率高
  4. 通常用信号量来实现进程对共享内存同步访问的控制

共享内存API

  1. shmget——创建/打开共享内存
  2. shmat——将共享内存与当前进程相关联
  3. shmdt——将当前进程与共享内存间脱离关联
  4. 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

喜欢的请收藏,谢谢你。星辰~念

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星辰~念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值