Linux IPC之共享内存

参考:

1)https://blog.csdn.net/ruizeng88/article/details/6702346

2)https://github.com/linw7/Skill-Tree/blob/master/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F.md

 

共享内存

共享内存(shared memory)是最简单的Linux进程间通信方式之一。使用共享内存,不同进程可以对同一块内存进行读写。由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝,所以,这种方式是效率最高、速度最快的进程间通信方式。

这种最大限度的自由也给共享内存带来了缺点:内核并不提供任何对共享内存访问的同步机制,比如同时对共享内存的相同地址进行写操作,则后写的数据会覆盖之前的数据。所以,使用共享内存一般还需要使用其他IPC机制(如信号量)进行读写同步与互斥。

基本原理 

了解Linux内存管理机制,就很容易知道共享内存的原理了。大家知道,内核对内存的管理是以页(page)为单位的,Linux下一般一个page大小是4k。而程序本身的虚拟地址空间是线性的,所以内核管理了进程从虚拟地址空间到起对应的页的映射。创建共享内存空间后,内核将不同进程虚拟地址的映射到同一个页面:所以在不同进程中,对共享内存所在的内存地址的访问最终都被映射到同一页面。下图演示了共享内存的工作机制:

Linux IPC之共享内存_第1张图片

相关接口

1)创建共享内存(SHared Memory GET):

int shmget(key_t key, int size, int flag);

返回:成功时返回一个和key相关的共享内存标识符,失败范湖范围-1。

key:为共享内存段命名,多个共享同一片内存的进程使用同一个key

size:共享内存容量。

flag:权限标志位,和open的mode参数一样。

2)连接到共享内存地址空间(SHared Memory ATtach):

void *shmat(int shmid, void *addr, int flag);

返回:返回值即共享内存实际地址。

shmid:shmget()返回的标识。

addr:决定以什么方式连接地址。

flag:访问模式。

3)从共享内存分离(SHared Memory DeTach):

int shmdt(const void *shmaddr);

返回:调用成功返回0,失败返回-1。

shmaddr:是shmat()返回的地址指针。

程序示例

下面的示例程序,a进程每一秒的向共享内存写入一个随机数,b进程每隔一秒从该共享内存读出该数。

/*
 * a.c
 * write a random number between 0 and 999 to the shm every 1 second
*/
#include
#include
#include
#include
#include
int main(){
	int shm_id;
	int *share;
	int num;
	srand(time(NULL));
	shm_id = shmget (1234, getpagesize(), IPC_CREAT);
	if(shm_id == -1){
		perror("shmget()");
	}
	share = (int *)shmat(shm_id, 0, 0);
	while(1){
		num = random() % 1000;
		*share = num;
		printf("write a random number %d\n", num);
		sleep(1);
	}
	return 0;
}
/*
 * b.c
 * read from the shm every 1 second
*/
#include
#include
#include
#include
#include
int main(){
	int shm_id;
	int *share;
	shm_id = shmget (1234, getpagesize(), IPC_CREAT);
	if(shm_id == -1){
		perror("shmget()");
	}
	share = (int *)shmat(shm_id, 0, 0);
	while(1){
		sleep(1);
		printf("%d\n", *share);
	}
	return 0;
}

 

Linux IPC之共享内存_第2张图片

Linux IPC之共享内存_第3张图片

你可能感兴趣的:(IPC,共享内存,面经)