Linux 18 IPC之共享内存shm

一、原理

共享内存是三个IPC(Inter-Process Communication)机制中的一个。
它允许两个不相关的进程访问同一个逻辑内存。
共享内存是在两个正在进行的进程之间传递数据的一种非常有效的方式。
大多数的共享内存的实现,
都把由不同进程之间共享的内存安排为同一段物理内存。

共享内存是由IPC为进程创建一个特殊的地址范围,
它将出现在该进程的地址空间中。
其他进程可以将同一段共享内存连接它们自己的地址空间中。
所有进程都可以访问共享内存中的地址,
就好像它们是由malloc分配的一样。

如果某个进程向共享内存写入了数据,
所做的改动将立刻被可以访问同一段共享内存的任何其他进程看到。

共享内存本身没有同步机制,需要程序自己保证(有点类似全局变量的读写需要加锁)共享内存的优点是简易性。
使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制,同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。
共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。
因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shm_id, const void *shm_addr, int shmflg);
int shmdt(const void *shm_addr);
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
1.shmget函数

用来创建共享内存

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

key:为共享内存段命名
size:以字节为单位的大小
shmflg:9bit的权限标志位

2.shmat函数

连接共享内存到进程地址空间

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

shm_id:shmget返回的共享内存ID
shm_addr:共享内存连接到当前进程空间的地址,通常为空指针,表示让系统来选择
shmflg:
SHM_RND:和shm_addr联合使用,用来控制连接当前进程空间的地址;
SHM_RDONLY:使连接的地址只读

3.shmdt函数

int shmdt(const void *shm_addr);
将共享内存从当前进程空间分离
shm_addr:shmat返回的地址

4.shmctl函数

int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
共享内存的控制函数

struct shmid_ds {
  uid_t shm_perm.uid;
  uid_t shm_perm.gid;
  mode_t shm_perm.mode;
}

cmd:有以下取值:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段

/* readshm.c */
/* 读数据 */
#include <stdio.h>     
#include <sys/types.h>     
#include <sys/ipc.h>     
#include <sys/shm.h>     
#include <unistd.h>
#include <string.h>

#define BUF_SIZE 1024     
#define MYKEY 25  
   
int  main()    
{    
	int shmid;    
	char * shmptr;    

	/* 获取共享内存ID */
	if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)    
	{    
    	printf("shmget error!\n");    
    	return 1;    
	}    
    
	if((shmptr = shmat(shmid,0,0)) == (void *)-1)    
	{    
    	printf("shmat error!\n");    
    	return 1;    
	}    
    
	while(1)    
	{    
    	printf("string :%s\n",shmptr);    /* 读共享内存数据 */   
    	if (strcmp(shmptr, "quit") == 0)
    	{
    		shmdt(shmptr);
    		return 0; 
    	}

    	sleep(5);    
	}    
    
	return 0;     
}    
writeshm.c
/* 写数据 */
#include <sys/types.h>     
#include <sys/ipc.h>     
#include <sys/shm.h>     
#include <stdio.h>     
#include <unistd.h>
#include <string.h>

#define BUF_SIZE 1024     
#define MYKEY 25     

int main()    
{    
	int shmid;    
	char *shmptr;    

	/* 创建共享内存 */
	if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)
	{    
		printf("shmget error \n");    
    	return 1;    
	}    

	/* 连接共享内存到进程地址空间 */
	if((shmptr =shmat(shmid,0,0))==(void *)-1)    
	{    
    	printf("shmat error!\n");    
    	return 1;    
	}    
    
	while(1)    
	{    
    	printf("input:");    
    	scanf("%s",shmptr);    /* 写共享内存数据 */
    	if (strcmp(shmptr, "quit") == 0)
    	{
    		//sleep(1);
    		shmdt(shmptr);
    		return 0; 
    	}
	}    
    
	return 0;     
}   

Makefile:


APP_READ = readshm
READ_OBJS = readshm.o
APP_WRITE = writeshm
WRITE_OBJS = writeshm.o

CC = gcc
INC = ./
CFLAG += -g

.PHONY : all

all : $(APP_READ) $(APP_WRITE)

$(APP_READ) : $(READ_OBJS)
	$(CC) $(CFLAG) $(READ_OBJS) -o $(APP_READ)

$(APP_WRITE) : $(WRITE_OBJS)
	$(CC) $(CFLAG) $(WRITE_OBJS) -o $(APP_WRITE)
	
%.o : %.c
	$(CC) -c $(CFLAG) $^ -o $@

.PHONY : clean

clean :
	rm -f *.o
	rm -f $(APP_READ) $(APP_WRITE)
	

参考 http://blog.csdn.net/zhaoyw2008/article/details/38787409

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值