linux 共享内存api,System V共享内存实例详解

1. 概述

System V共享内存在概念上类似于Posix共享内存,代之以调用shm_Open后调用mmap的是,先调用shmget,再调用shmat。

对于每个System V共享内存,内核都维护如下的信息结构,它定义在sys/shm.h头文件中,其中带注释的是我们需要关注的成员。

struct shmid_ds

{

struct ipc_perm shm_perm;

size_t shm_segsz; //共享内存区大小

pid_t shm_lpid;

pid_t shm_cpid;

shmatt_t shm_nattch;

shmat_t shm_cnattch;

time_t shm_atime;

time_t shm_dtime;

time_t shm_ctime;

};

2. System V共享内存API

shmget

shmget用于创建一个新的共享内存或打开一个已存在的共享内存。

//成功返回共享内存标识符,

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

参数size是共享内存区大小,其余两个参数含义及用法和System V信号量一样

当实际操作为创建新的共享内存时,该内存区size个字节均被初始化为0

当实际操作为打开已有共享内存时,size可设为0,oflag设为需要的读写权限

shmat

shmat用于把shmget创建或打开的共享内存连接到调用进程的地址空间。

//成功返回映射区起始地址,失败返回-1

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

shmid是shmget返回的标识符

shmaddr推荐设为NULL,表示由系统决定映射区起始地址

flag一般设为0,因为只要调用进程具有共享内存的读写权限,那么映射区内存就也可以读写

flag也可以设为SHM_RDONLY限定只读访问

shmdt

shmdt删除由shmat建立的连接。

//成功返回0,失败返回-1

int shmdt(const void *shmaddr);

shmctl

shmctl用于对共享内存的各种控制操作。

//成功返回0,失败返回-1

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

cmd可使用的命令有三个:

IPC_RMID:从系统中删除共享内存,此时buf参数设为NULL即可

IPC_STAT:通过buf返回共享内存对应的shmid_ds结构,一般用此命令获取共享内存区大小

IPC_SET:通过buf设置共享内存对应shmid_ds结构中的shm_perm.uid、shm_perm.gid和shm_perm.mode

3. 简单的程序

代码实现

common.h

#ifndef _COMMON_H_

#define _COMMON_H_

#include

#include

#include

#include

#include

#include

#define FTOK_FILE "/home/delphi/ftok.file"

#define FTOK_ID 1

#define SHM_RD_PERMISSION 0444

#define SHM_WR_PERMISSION 0222

#define SHM_RW_PERMISSION (SHM_RD_PERMISSION | SHM_WR_PERMISSION)

#endif

shmcreate.c

#include "common.h"

int main(int argc, char **argv)

{

int length = atoi(argv[1]);

int oflag = IPC_CREAT | SHM_RW_PERMISSION;

int shmid = shmget(ftok(FTOK_FILE, FTOK_ID), length, oflag);

if (shmid >= 0)

{

printf("shmget create success, shmid = %d\n", shmid);

}

return 0;

}

shmrmid.c

#include "common.h"

int main(int argc, char **argv)

{

int shmid = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);

shmctl(shmid, IPC_RMID, NULL);

return 0;

}

shmwrite.c

#include "common.h"

int main(int argc, char **argv)

{

int shmid;

unsigned char *shmadd;

struct shmid_ds buf;

int i;

shmid = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);

shmadd = shmat(shmid, NULL, 0);

shmctl(shmid, IPC_STAT, &buf);

for (i = 0; i < buf.shm_segsz; i++)

{

*shmadd++ = i % 256;

}

return 0;

}

shmread.c

#include "common.h"

int main(int argc, char **argv)

{

int shmid;

unsigned char *shmadd;

unsigned char v;

struct shmid_ds buf;

int error = 0;

int i;

shmid = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);

shmadd = shmat(shmid, NULL, 0);

shmctl(shmid, IPC_STAT, &buf);

for (i = 0; i < buf.shm_segsz; i++)

{

v = *shmadd++;

if (v != (i % 256))

{

printf("error: shmadd[%d] = %d\n", i, v);

error++;

}

}

if (error == 0)

{

printf("all of read is ok\n");

}

return 0;

}

代码测试

ad410125495a93ba18dd5d8383661fb7.png

9faf679dc6ac8184ec06fc65033e9e9d.png

03d07a0d4f8b2c80349e7e2d2dd93e8d.png

de6287432fd3a919ac23fa14e05fc849.png

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值