linux 关闭共享内存,Linux共享内存区

用几个小程序简单总结一下UNPv2讲的三种内存共享的方法。

一、内存映射文件

(1)内存映射文件(可用在无亲缘关系的进程间共享)

#include

#include

#include

#include

#include

#include

#include

#define FILE_MODE       (S_IRWXU | S_IRWXG | S_IRWXO)

#define IPC_FILE        "/tmp/temp.1"

intmain(intargc,char**argv)

{

intfd = -1, i, nloop, zero = 0;

int*ptr;

sem_t mutex;

if(argc != 2)

{

printf("usage: incr \n");

return-1;

}

nloop = atoi(argv[1]);

fd = open(IPC_FILE, O_RDWR | O_CREAT, FILE_MODE);

if(-1 == fd)

{

printf("open %s error!\n", IPC_FILE);

return-1;

}

write(fd, &zero, sizeof(int));

ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

close(fd);

//sem_init(&mutex, 1, 1);//有误,无名信号量需位于共享内存才可在进程间共享

setbuf(stdout, NULL);

if(fork() == 0)

{

for(i = 0; i

{

sem_wait(&mutex);

printf("child: %d\n", (*ptr)++);

sem_post(&mutex);

}

return0;

}

for(i = 0; i

{

sem_wait(&mutex);

printf("parent: %d\n", (*ptr)++);

sem_post(&mutex);

}

return0;

}

(2)匿名内存映射(用于有亲缘关系的进程间共享。flags:MAP_SHARED | MAP_ANONYMOUS  或 /dev/zero设备,以MAP_ANONYMOUS为例)

#include

#include

#include

#include

#include

#include

#include

intmain(intargc,char**argv)

{

inti, nloop;

int*ptr;

sem_t mutex;

if(argc != 2)

{

printf("usage: incr_anonymous \n");

return-1;

}

nloop = atoi(argv[1]);

ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);/* 匿名映射的内存区被初始化为0 */

//sem_init(&mutex, 1, 1);//有误,无名信号量需位于共享内存才可在进程间共享

setbuf(stdout, NULL);

if(fork() == 0)

{

for(i = 0; i

{

sem_wait(&mutex);

printf("child: %d\n", (*ptr)++);

sem_post(&mutex);

}

return0;

}

for(i = 0; i

{

sem_wait(&mutex);

printf("parent: %d\n", (*ptr)++);

sem_post(&mutex);

}

return0;

}

二、Posix共享内存区对象

(1)server.c创建共享内存区和有名信号量,并退出,posix共享内存区和有名信号量并不会因为server退出而被删,除非被显式删除。创建共享内存区对象和有名信号量的文件在/dev/shm中。

#include

#include

#include

#include

#include

#include

#include

#define FILE_MODE       (S_IRWXU | S_IRWXG | S_IRWXO)

#define SH_NAME         "shm1"

#define SEM_NAME        "sem1"

typedefstruct

{

intcount;

}SHM_STRUCT;

sem_t *mutex;

intmain(intargc,char**argv)

{

intfd;

SHM_STRUCT *ptr;

shm_unlink(SH_NAME);

fd = shm_open(SH_NAME, O_RDWR | O_CREAT | O_EXCL, FILE_MODE);

if(fd

{

printf("create shared memory error!\n");

return-1;

}

ftruncate(fd, sizeof(SHM_STRUCT));

ptr = mmap(NULL, sizeof(SHM_STRUCT), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

close(fd);

sem_unlink(SEM_NAME);

mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1);

if(mutex == NULL)

{

printf("create semaphore error!\n");

return-1;

}

sem_close(mutex);

return0;

}

(2)client.c打开共享内存区,并对count进行累加。

#include

#include

#include

#include

#include

#include

#include

#define FILE_MODE       (S_IRWXU | S_IRWXG | S_IRWXO)

#define SH_NAME         "shm1"

#define SEM_NAME        "sem1"

#define LOOP_NUM        "10000"

typedefstruct

{

intcount;

}SHM_STRUCT;

sem_t *mutex;

intmain(intargc,char**argv)

{

intfd, i, nloop;

pid_t pid;

SHM_STRUCT *ptr;

nloop = atoi(LOOP_NUM);

fd = shm_open(SH_NAME, O_RDWR, FILE_MODE);

if(fd

{

printf("open share memory error!\n");

return-1;

}

ptr = mmap(NULL, sizeof(SHM_STRUCT), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

close(fd);

mutex = sem_open(SEM_NAME, 0);

if(mutex == NULL)

{

printf("open semaphore error!\n");

return-1;

}

pid = getpid();

for(i = 0; i

{

sem_wait(mutex);

printf("pid %ld: %d\n", (long)pid, ptr->count++);

sem_post(mutex);

}

return0;

}

(3)client退出后,共享内存区对象还是存在于系统中的,如果不删除,则之后运行client后,共享内存区里的count变量会不断累加。可以用shm_unlink()和sem_unlink()删除共享内存区对象和有名信号量。

#include

#include

#include

#include

#include

#include

#include

intmain(intargc,char**argv)

{

if(argc != 3)

{

printf("error command!\n");

return-1;

}

shm_unlink(argv[1]);

sem_unlink(argv[2]);

return0;

}

三、system V共享内存区

虽然现在glibc都支持posix共享内存,但在使用uclibc的嵌入式环境中则是不一定的,还需要用到system v接口。这里先只给出system v共享内存的例子,而system v信号量则留待下一篇写。

首先,封装一下几个接口。

(1)shmOpt.h

#ifndef __SHMOPT_H__

#define __SHMOPT_H__

#include

#define SHM_KEY 1234

#define SVSHM_MODE      ((SHM_R) | (SHM_W) | (SHM_R >> 3) | (SHM_R >> 6))

intcreateShm(key_t key,size_tsize);/* 创建共享内存区 */

void*attachShm(key_t key);/* 连接共享内存区 */

intdettachShm(constvoid*shmaddr);/* 断接共享内存区 */

intdestroyShm(key_t key);/* 删除共享内存区 */

intsetShmParam(key_t key,structshmid_ds *buff);/* 设置共享内存区参数 */

intgetShmParam(key_t key,structshmid_ds *buff);/* 获取共享内存区参数 */

#endif

(2)shmOpt.c

#include

#include "shmOpt.h"

intcreateShm(key_t key,size_tsize)

{

intoflag = SVSHM_MODE | IPC_CREAT;

intid = shmget(key, size, oflag);

if(id

{

printf("%s:create shared memory error!\n", __FUNCTION__);

}

returnid;

}

void*attachShm(key_t key)/* fail:NULL */

{

intoflag = SVSHM_MODE | IPC_CREAT;

intid;

char*ptr;

id = shmget(key, 0, oflag);

if(id

{

printf("%s:get shared memory error!\n", __FUNCTION__);

returnNULL;

}

ptr = shmat(id, NULL, 0);

if(*ptr == -1)

{

printf("%s:attach shared memory error!\n", __FUNCTION__);

returnNULL;

}

returnptr;

}

intdettachShm(constvoid*shmaddr)

{

returnshmdt(shmaddr);

}

intdestroyShm(key_t key)

{

intid;

intoflag = SVSHM_MODE | IPC_CREAT;

intret;

id = shmget(key, 0, oflag);

if(id

{

printf("%s:get shared memory error!\n", __FUNCTION__);

return-1;

}

ret = shmctl(id, IPC_RMID, NULL);

if(ret

{

printf("%s:delete shared memory error!\n", __FUNCTION__);

return-1;

}

return0;

}

intsetShmParam(key_t key,structshmid_ds *buff)

{

intid;

intoflag = SVSHM_MODE | IPC_CREAT;

intret;

id = shmget(key, 0, oflag);

if(id

{

printf("%s:get shared memory error!\n", __FUNCTION__);

return-1;

}

ret = shmctl(id, IPC_SET, buff);

if(ret

{

printf("%s:set parameters error!\n", __FUNCTION__);

return-1;

}

return0;

}

intgetShmParam(key_t key,structshmid_ds *buff)

{

intid;

intoflag = SVSHM_MODE | IPC_CREAT;

intret;

id = shmget(key, 0, oflag);

if(id

{

printf("%s:get shared memory error!\n", __FUNCTION__);

return-1;

}

ret = shmctl(id, IPC_STAT, buff);

if(ret

{

printf("%s:get parameters error!\n", __FUNCTION__);

return-1;

}

return0;

}

以下是例子程序。由于没有同步保护,因此首先先用server创建共享内存区,然后再多次调用client看count变量是否能持续累加即可,最后由shmRemove删除共享内存区。

(1)server.c

#include

#include "shmOpt.h"

typedefstruct

{

intcount;

}SHM_STRUCT;

intmain()

{

intid;

id = createShm(SHM_KEY, sizeof(SHM_STRUCT));

if(id

{

printf("createShm error!\n");

return-1;

}

return0;

}

(2)client.c

#include

#include "shmOpt.h"

#define LOOP_NUM 1000

typedefstruct

{

intcount;

}SHM_STRUCT;

intmain()

{

SHM_STRUCT *ptr;

structshmid_ds buff;

inti;

ptr = attachShm(SHM_KEY);

if(!ptr)

{

printf("cannot attach shm!\n");

return-1;

}

for(i = 0; i

{

ptr->count++;

}

printf("ptr->count=%d\n", ptr->count);

printf("======================\n");

if(getShmParam(SHM_KEY, &buff)

{

printf("get shmParam error!\n");

return-1;

}

printf("shm size:%d--sizeof(SHM_STRUCT):%d\n", buff.shm_segsz,sizeof(SHM_STRUCT));

return0;

}

(3)shmRemove.c

#include

#include "shmOpt.h"

intmain()

{

destroyShm(SHM_KEY);

return0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值