码迷,mamicode.com
首页 > 系统相关 > 详细

Linux进程间通信-共享内存

时间:2015-06-30 15:08:00      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:linux进程间通信   共享内存   

         共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输。这种高效带来的问题是,我们必须使用其他辅助手段来同步进程对内存的访问,否则会产生竞态条件(一般我们与信号量结合使用)。因此,共享内存通常和其他进程间通信方式一起使用。

技术分享

Linux共享内存的API都定义在sys/shm.h头文件中,包括4个系统调用:shmget、shmat、shmdt和shmctl

#include <sys/shm.h>
int sys_shmget (key_t key, int size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int sys_shmdt (char *shmaddr);
int shmctl(int shmid,int cmd,struct shmid_ds *buf);

shmget系统调用创建一段新的共享内存,或者获取一段已经存在的共享内存。

和shmget系统调用一样,key参数是一个键值,用来标识一段全局唯一的共享内存。size参数指定共享的大小,单位是字节。如果是创建新的共享内存,则size值必须被指定。如果是获取已经存在的共享内存,则可以把size设置为0。

shmflg参数的使用和含义与semget系统调用的semflag参数相同

shmget成功时返回一个正整数,它是共享内存的标识符。shmget失败时返回-1,并设置errno。如果shmget用于创建共享内存,则这段共享内存的所有字节都被初始化为0,与之关联的内核数据结构shmid_ds将被创建并初始化。


shmatshmdt用于关联/分离共享内存,共享内存被创建/获取后,我们不能立即访问它,需要先将它关联到进程的地址空间中,使用完后,再从地址空间分离。

其中shmid参数是由shmget调用返回的共享内存标识符。shmaddr参数指定共享内存关联到进程的哪块地址空间,最终的效果还是受到shmflg参数的可选标志SHM_RND的影响:

如果shmaddr为NULL,则被关联的地址由操作系统选择。这是推荐的做法,以确保可移植性。


shmctl用于控制共享内存的某些属性,shmid参数是由shmget调用返回的共享内存标识符。cmd参数指定要执行的命令。shmctl成功时的返回值取决于cmd参数,失败时返回-1,并设置errno


共享内存程序示例

#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define err_sys(msg) 	do { perror(msg); exit(-1); } while(0)

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short int *array;
	struct seminfo * __buf;
};

void pv(int sem_id, int op)
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = op;
	sem_b.sem_flg = SEM_UNDO;
	semop(sem_id, &sem_b, 1);
}

int main(void)
{
	int sem_id = semget(IPC_PRIVATE, 1, 0666);
	int shm_id = shmget(IPC_PRIVATE, 4, 0666);

	union semun sem_un;
	sem_un.val = 1;
	semctl(sem_id, 0, SETVAL, sem_un);

	pid_t pid = fork();
	if(pid < 0)
		err_sys("fork");
	else if(pid == 0)
	{
		char *shmp;
		pv(sem_id, -1);
		shmp = shmat(shm_id, NULL, 0);
		if(shmp == (char *)(-1))
			err_sys("child shmat");
		*(int *)shmp = 10;
		shmdt(shmp);
		printf("child get the sem and would sleep 2s.\n");
		sleep(2);
		pv(sem_id, 1);
		exit(0);
	}
	else
	{
		char *shmp;
		sleep(1);
		pv(sem_id, -1);
		shmp = shmat(shm_id, NULL, 0);
		if(shmp == (char *)(-1))
			err_sys("child shmat");
		printf("shm: %d\n", *(int *)shmp);
		shmdt(shmp);
		printf("parent get the sem and would sleep 2s.\n");
		sleep(2);
		pv(sem_id, 1);
	}

	waitpid(pid, NULL, 0);
	shmctl(shm_id, IPC_RMID, NULL);
	semctl(sem_id, 0, IPC_RMID, sem_un);

	return 0;
}

参考:

1、《Linux高性能服务器编程》 第13章 多进程编程/共享内存

2、Linux 进程间通信 - 共享内存 (这个讲的比较详细....)

版权声明:本文为博主原创文章,未经博主允许不得转载。

Linux进程间通信-共享内存

标签:linux进程间通信   共享内存   

原文地址:http://blog.csdn.net/u012796139/article/details/46692787

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!