共享内存区

来源:互联网 发布:华住酒店员工流失数据 编辑:程序博客网 时间:2024/06/05 17:12
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 processessetbuf(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 followsptr = 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 processessetbuf(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
原创粉丝点击