标签: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);
l shmget系统调用创建一段新的共享内存,或者获取一段已经存在的共享内存。
和shmget系统调用一样,key参数是一个键值,用来标识一段全局唯一的共享内存。size参数指定共享的大小,单位是字节。如果是创建新的共享内存,则size值必须被指定。如果是获取已经存在的共享内存,则可以把size设置为0。
shmflg参数的使用和含义与semget系统调用的semflag参数相同
shmget成功时返回一个正整数,它是共享内存的标识符。shmget失败时返回-1,并设置errno。如果shmget用于创建共享内存,则这段共享内存的所有字节都被初始化为0,与之关联的内核数据结构shmid_ds将被创建并初始化。
l shmat和shmdt用于关联/分离共享内存,共享内存被创建/获取后,我们不能立即访问它,需要先将它关联到进程的地址空间中,使用完后,再从地址空间分离。
其中shmid参数是由shmget调用返回的共享内存标识符。shmaddr参数指定共享内存关联到进程的哪块地址空间,最终的效果还是受到shmflg参数的可选标志SHM_RND的影响:
如果shmaddr为NULL,则被关联的地址由操作系统选择。这是推荐的做法,以确保可移植性。
l 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进程间通信 共享内存
原文地址:http://blog.csdn.net/u012796139/article/details/46692787