linux共享内存编码,Linux共享内存(示例代码)

1.什么是共享内存

在前面讲虚拟内存机制时,有讲到Linux的内存映射机制:

初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来。

由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进程私有访问。

当共享访问时,一个进程的对该对象的修改会显示到其他进程。

当私有访问时,修改时会产生保护故障,内核会拷贝这个私有对象,修改的是这个新对象,其他进程指向的是原来的对象。

所以,共享内存是指不同进程访问同一个逻辑内存。

2.共享内存的使用

Linux提供了一组共享内存API,声明在头文件sys/shm.h中。

1)shmget函数:新建共享内存

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

key:共享内存键值,可以理解为共享内存的唯一性标记。

size:共享内存大小

shmflag:创建进程和其他进程的读写权限标识。

返回值:相应的共享内存标识符,失败返回-1

2)shmat函数:连接共享内存到当前进程的地址空间

void *shmat(int shm_id,const void *shm_addr,int shmflg);

shm_id:共享内存标识符

shm_addr:指定共享内存连接到当前进程的地址,通常为0,表示由系统来选择。

shmflg:通常为0

返回值:指向共享内存第一个字节的指针,失败返回-1

3)shmdt函数:当前进程分离共享内存

int shmdt(const void *shmaddr);

4)shmctl函数

和信号量的semctl函数类似,控制共享内存

int shmctl(int shm_id,int command,struct shmid_ds *buf);

shm_id:共享内存标识符

command: 有三个值

IPC_STAT:获取共享内存的状态,把共享内存的shmid_ds结构复制到buf中。

IPC_SET:设置共享内存的状态,把buf复制到共享内存的shmid_ds结构。

IPC_RMID:删除共享内存

buf:共享内存管理结构体。具体结构可参考定义。

3.共享内存需要注意的问题

共享内存没有同步机制,当多个进程同时向共享内存读写数据时,我们需要使用互斥锁,读写锁,信号量,条件变量等来确保数据的一致性。

4.共享内存使用示例

我们编写了两个程序shmread.c,shmwrite.c分别对共享内存读和写。

需要做到可写,然后可读,然后可写,然后可读,循环下去,直到写入的是"end",结束写读进程。

我们使用了前面讲的信号量来处理读写同步的问题。

示例代码如下:

shm_data.h

#pragma once

#define TEXT_SZ 2048

structshared_use_st

{chartext[TEXT_SZ];

};

shmread.c

#include#include#include#include#include"shmdata.h"union semun

{intval;struct semid_ds *buf;

unsignedshort *arry;

};intsem_id;intset_semvalue()

{//用于初始化信号量,在使用信号量前必须这样做

union semun sem_union;

sem_union.val= 1;if(semctl(sem_id, 0, SETVAL, sem_union) == -1)return 0;return 1;

}voiddel_semvalue()

{//删除信号量

union semun sem_union;if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

fprintf(stderr,"Failed to delete semaphore\n");

}intsemaphore_p()

{structsembuf sem_b;

sem_b.sem_num= 0;

sem_b.sem_op= -1;//P()

sem_b.sem_flg =SEM_UNDO;if(semop(sem_id, &sem_b, 1) == -1)

{

fprintf(stderr,"semaphore_p failed\n");return 0;

}return 1;

}intsemaphore_v()

{structsembuf sem_b;

sem_b.sem_num= 0;

sem_b.sem_op= 1;//V()

sem_b.sem_flg =SEM_UNDO;if(semop(sem_id, &sem_b, 1) == -1)

{

fprintf(stderr,"semaphore_v failed\n");return 0;

}return 1;

}intmain()

{void *shm=NULL;struct shared_use_st *shared;int shmid;//共享内存标识符//创建共享内存

shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);if(shmid==-1)

{

fprintf(stderr,"shmget failed\n");

exit(EXIT_FAILURE);

}//将共享内存连接到当前进程的地址空间

shm = shmat(shmid,0,0);if(shm==(void*)-1)

{

fprintf(stderr,"shmat failed\n");

exit(EXIT_FAILURE);

}

printf("memory attached at %x\n",(int)shm);//设置共享内存

shared = (struct shared_use_st*)shm;//新建信号量

sem_id = semget((key_t)1234,1,0666|IPC_CREAT);//信号量初始化

if(!set_semvalue())

{

fprintf(stderr,"init failed.\n");

exit(EXIT_FAILURE);

}while(1)

{if(!semaphore_p())

exit(EXIT_FAILURE);

fflush(stdout);

printf("you wrote:%s",shared->text);if(!semaphore_v())

exit(EXIT_FAILURE);if(strncmp(shared->text,"end",3)==0)break;

sleep(1);

}//删除信号量

del_semvalue();//把共享内存从当前进程中分离

if(shmdt(shm)==-1)

{

fprintf(stderr,"shmdt failed\n");

exit(EXIT_FAILURE);

}//删除共享内存

if(shmctl(shmid,IPC_RMID,0)==-1)

{

fprintf(stderr,"shmctl(IPC_RMID) failed");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

shmwrite.c

#include#include#include#include#include#include"shmdata.h"

intsem_id;intsemaphore_p()

{//对信号量做减1操作,即等待P(sv)

structsembuf sem_b;

sem_b.sem_num= 0;

sem_b.sem_op= -1;//P()

sem_b.sem_flg =SEM_UNDO;if(semop(sem_id, &sem_b, 1) == -1)

{

fprintf(stderr,"semaphore_p failed\n");return 0;

}return 1;

}intsemaphore_v()

{//这是一个释放操作,它使信号量变为可用,即发送信号V(sv)

structsembuf sem_b;

sem_b.sem_num= 0;

sem_b.sem_op= 1;//V()

sem_b.sem_flg =SEM_UNDO;if(semop(sem_id, &sem_b, 1) == -1)

{

fprintf(stderr,"semaphore_v failed\n");return 0;

}return 1;

}intmain()

{

sem_id= semget((key_t)1234,1,0666|IPC_CREAT);void *shm =NULL;struct shared_use_st *shared =NULL;char buffer[200];intshmid;//创建共享内存

shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);if(shm==-1)

{

fprintf(stderr,"shmget failed\n");

exit(EXIT_FAILURE);

}//将共享内存连接到当前进程的地址空间

shm = shmat(shmid,(void*)0,0);if(shm == (void*)-1)

{

fprintf(stderr,"shmat failed\n");

exit(EXIT_FAILURE);

}

printf("memory attached at %x\n",(int)shm);//设置共享内存

shared = (struct shared_use_st*)shm;while(1)

{if(!semaphore_p())

exit(EXIT_FAILURE);//向共享内存中写入数据

fflush(stdout);

printf("Enter some text...\n");

fgets(buffer,200,stdin);

strncpy(shared->text,buffer,TEXT_SZ);if(!semaphore_v())

exit(EXIT_FAILURE);if(strncmp(shared->text,"end",3)==0)break;

sleep(1);

}//把共享内存从当前进程中分离

if(shmdt(shm)==-1)

{

fprintf(stderr,"shmdt failed\n");

exit(EXIT_FAILURE);

}

sleep(2);

exit(EXIT_SUCCESS);

}

输出结果:

20180110193113838134.png

20180110193113840087.png

20180110193113842040.png

5.共享内存的优缺点

1)进程间通信方便,快速。

2)没有提供同步机制,我们需要使用互斥锁,读写锁,信号量,条件变量等来确保数据的一致性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值