共享内存区

24 篇文章 0 订阅
7 篇文章 0 订阅
Posix提供了无亲缘关系进程间共享内存区的两种方法:
1.内存映射文件
  由open函数打开,由mmap函数把得到的描述字映射到当前进程地址空间的一个文件。

#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
   addr可以指定为描述字fd应被映射到的进程内空间起始地址。通常被指定为NULL,由内核自己决定。len为映射的字节数。offset常设置为0,prot常见值为PROT_READ|PROT_WRITE。
   prot常用参数表:
   prot                      description
   PROT_READ                 数据可读
   PROT_WRITE                数据可写
   PROT_EXEC                 数据可执行
   PROT_NONE                 数据不可访问
   flags常用参数表:
   flags                     description
   MAP_SHARED		     变动是共享的
   MAP_PRIVATE               变动是私有的
   MAP_FIXED                 准确解释addr参数
父子进程之间共享内存区的方法之一是,父进程在调用fork前先指定MAP_SHARED调用mmap()。

int munmap(void *addr, size_t len);
4.4BSD提供了匿名内存映射,避免了文件的创建和打开。其办法是把mmap的flags参数指定成MAP_SHARED|MAP_ANON,fd指定为-1。offset参数被忽略。这样的内存被初始化为0。使用方式类似这样:
   int *ptr = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
与需要打开文件的mmap相比,增加了MAP_ANON,fd = -1. offset值随意。

2.共享内存区对象
  由shm_open打开一个Posix名字,所返回描述字由mmap函数映射到当前进程地址空间。
  int shm_open(const char *name, int oflag, mode_t mode);
  int shm_unlink(const char *name);
  oflag参数必须或者含有O_RDONLY,或者O_RDWR标志,也可以指定O_CREAT、O_EXCL或O_TRUNC。如果随O_RDWR指定O_TRUNC,而且所需的共享内存区对象已经存在,那么它将被截短成0长度。一般shm_open的oflag与mmanp的第三个参数读写权限相对应。
  mode参数总是必须指定。

处理mmap的时候,普通文件或共享内存区对象的大小都可以通过调用ftruncate修改。
  #include <unistd.h>
  int ftruncate(int fd, off_t length);
允许将普通文件和共享内存区对象的大小指定为比原来的大或小。

//file_shm.c
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

struct shared
{
	sem_t mutex;
	int count;
}shared;

int main(int argc, char **argv)
{
	int fd, i, nloop;
	struct shared *ptr;

	if(argc != 3)
	{
		perror("usage: memshared <pathname> <#loops>");
		exit(0);
	}
	nloop = atoi(argv[2]);

	fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE);
	write(fd, &shared, sizeof(struct shared));
	// mmap returns void*	
	ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	close(fd);

	sem_init(&ptr->mutex, 1, 1);// 2nd param 1 means sem is shared among different processes

	setbuf(stdout, NULL);

	if(fork() == 0)
	{
		for(i = 0; i < nloop; i++)
		{
			sem_wait(&ptr->mutex);
			printf("child:%d\n", ptr->count++);
			sem_post(&ptr->mutex);
		}
		exit(0);
	}

	for(i = 0; i < nloop; i++)
	{
		sem_wait(&ptr->mutex);
		printf("parent:%d\n", ptr->count++);
		sem_post(&ptr->mutex);
	}
	sem_destroy(&ptr->mutex);

	return 0;

}

// obj_shm.c
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

struct shared
{
	sem_t mutex;
	int count;
}shared;

int main(int argc, char **argv)
{
	int fd, i, nloop;
	struct shared *ptr;

	if(argc != 2)
	{
		perror("usage: memshared <#loops>");
		exit(0);
	}
	nloop = atoi(argv[1]);

	// mmap returns void*
	// BSD 4.4 provide a way of mmaping without opening a file, as follows
	ptr = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);

	sem_init(&ptr->mutex, 1, 1);// 2nd param 1 means sem is shared among different processes

	setbuf(stdout, NULL);

	if(fork() == 0)
	{
		for(i = 0; i < nloop; i++)
		{
			sem_wait(&ptr->mutex);
			printf("child:%d\n", ptr->count++);
			sem_post(&ptr->mutex);
		}
		exit(0);
	}

	for(i = 0; i < nloop; i++)
	{
		sem_wait(&ptr->mutex);
		printf("parent:%d\n", ptr->count++);
		sem_post(&ptr->mutex);
	}
	sem_destroy(&ptr->mutex);

	return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值