Linux共享内存通信

Linux共享内存通信  

共享内存是Linux的一种进程间直接进行数据交换的通信方式,直接将共享的内存页面通过附接,映射到相互通信的进程各自的虚拟地址空间中,从而使多个进程可以直接访问同一个物理内存页面,如同访问自己的私有空间一样。

共享内存的通信方式是通过将可以共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的。因此,这些进程之间的读写操作的同步问题操作系统无法实现,必须由诸共享该内存的进程去控制。

注意,同步访问时程序员的责任,共享内存没有提供任何共享方法,没有自动的方法来实现内存保护之类的功能

共享内存的通信方式是通过将可以共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的。因此,这些进程之间的读写操作的同步问题操作系统无法实现,必须由诸共享该内存的进程去控制。

注意,同步访问时程序员的责任,共享内存没有提供任何共享方法,没有自动的方法来实现内存保护之类的功能

4个系统调用函数:
创建共享内存:
int  shmid = int shmget ( key_t key,  int size,  int flag ):
key——共享存储区关键字,可以由用户指定,如果使用IPC_PRIVATE其值由系统产生。
size ——存储区的大小(字节数)。如果存储区定义为字符型,则大小为定义的字符个数;如果存储区定义为整型,大小可以使用sizeof (int)加以定义。
flag——用户设置的标志或访问方式,与消息缓冲shmget中的含义相同,在实验中,可以使用0666|IPC_CREAT,表示任意进程可读可写。
正确返回 共享存储区的内部标示符 shmid; 错误返回-1

映射共享内存:
字符型共享内存:
viraddr =(char*)shmat ( shmid,  shmaddr,  shmflag );
数值型共享内存:
viraddr =(int*)shmat ( shmid,  shmaddr,  shmflag );
正确返回共享存储区附接后的虚地址viraddr; 错误返回-1
shmid——共享存储区的描述符,可以由shmget()的返回值得到;
shmaddr——用户提供的共享存储区附接的虚地址。(若shmaddr为0 ,则表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间);
shmflag——规定了对该存储区的操作权限,以及系统是否要对用户规定的地址做舍除操作。如果flag中设置了SHM_RND表示操作系统在必要时舍去这个地址。(如果设置了SHM_RDONLY则表示只允许读,flag为0表示可读可写)。
viraddr——附接的虚地址,若定义为char *viraddr,则该共享内存作为字符存储区使用,若定义为int *viraddr,则该共享内存作为整型存储区使用。

撤销映射:
命令格式:
int shmdt(const void *shmaddr)
功能:
将一个共享存储区从指定进程的虚拟地址空间断开。
参数说明:
shmaddr——系统调用shmat()所返回的虚地址。
返回值: 正确返回:0 错误返回-1。

对共享内存操作:
命令格式:
shmctl(int shmid, int cmd, struct shmid_ds *buf)
功能:
对与共享存储区关联的各种参数进行操作,从而对共享存储区进行控制包括删除共享存储区。
参数说明:
shmid——共享存储区的内部标识符,由shmget()调用返回;
buf——用户级数据结构地址,其结构类型与系统定义的shmid_ds一致,可以用0。
cmd——规定操作的类型。其规定如下:
IPC_STAT 返回包含在指定的shmid相关数据结构中的状态信息,并把它放置在用户存储区中的*buf指针所指的数据结构中。执行此命令的进程必须有读取允许权。
 IPC_SET 对于指定的shmid,为它设置有效用户和小组标识符和操作存取权。
 IPC_RMID删除指定的shmid以及与它相关的共享存储区的数据结构。
SHM_LOCK在内存中锁定指定的共享存储区,必须是超级用户才可以进行此项操作。

所用头函数:
#include <sys/ipc.h>
#include <sys/shm.h>

[例1]用共享内存的通信方法来实现例4-5的功能,通过先运行发送进程然后再运行接收进程的方式来实现同步。

发送进程  sndshm.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h> 
#include<sys/types.h>
#include<linux/shm.h>
main()
{
int shmid; //定义共享内存内部标识shmid  
char *viraddr; //定义附接共享内存的虚拟地址 
char buffer[BUFSIZ]; //定义存放信息的字符串 
shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT); //创建共享内存 
viraddr=(char*)shmat(shmid, 0,0); //附接到进程的虚拟地址空间 
while(1)  //循环输入信息 
puts("Enter some text:");
fgets(buffer,BUFSIZ,stdin); //从键盘输入信息 
strcat(viraddr,buffer);       //采用追加方式写到共享内存 
if(strncmp(buffer,"end",3)==0) //输入为“end”时结束 
break;
}
shmdt(viraddr);  //断开附接 
exit(0);
}

接收进程  rcvshm.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<linux/shm.h>
main()
{
int shmid;
char *viraddr;
shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);  //获取共享内存 
viraddr=shmat(shmid, 0,0); //附接到进程的虚拟地址空间 
while(1)
printf("Your message is :\n%s",viraddr);//一直输出信息内容  
shmdt(viraddr);  //断开附接 
shmctl(shmid,IPC_RMID,0);  //撤消共享内存 
exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值