Posix共有メモリ
Posix.1では、無関係なプロセス間でのメモリ共有を行う方法を2種類提供している。
shm_open関数、shm_unlink関数
Posix共有メモリの使用には、2ステップの処理が必要。shm_openで用いた名前引数は、このメモリを他のプロセスから共有する場合に用いる名前になる。
#include <sys/mman.h> int shm_open(const char *name, int oflag, mode_t mode); int shm_unlink(const char *name); 戻り値:成功なら0、エラーなら−1
ftruncate関数、fstat関数
mmapを用いる際には、通常ファイルまたは共有メモリオブジェクトのサイズを、ftruncateで変更することができる。#include <unistd.h> int ftruncate(int fd, off_t length); 戻り値:成功なら0、エラーなら−1
ftruncateの定義について
ディスクリプタを指定して、そのディスクリプタの情報を取得する
#include <sys/types.h> #include <sys/stat.h> int fstat(int fd, struct stat *buf); 戻り値:成功なら0、エラーなら−1
fdが共有メモリオブジェクトを参照している場合に意味を持つのは、4つのメンバのみ
struct stat { mode_t st_mode; uid_t st_uid; gid_t st_gid; off_t st_size; };
//Posix共有メモリ #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH) void write_shm() { int i, fd; struct stat stat; unsigned char *ptr; fd = shm_open("/posix_shm", O_RDWR|O_CREAT, FILE_MODE); ftruncate(fd, 1024); fstat(fd, &stat); ptr = mmap(NULL, stat.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); close(fd); //Write for (i = 0; i < stat.st_size; i++) { *ptr++ = i % 256; } } void read_shm() { int i, fd; struct stat stat; unsigned char c, *ptr; fd = shm_open("/posix_shm", O_RDONLY, FILE_MODE); fstat(fd, &stat); ptr = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); close(fd); for (i = 0; i < stat.st_size; i++) { if ( (c = *ptr++) != (i % 256) ) { printf("error : "); } printf("ptr[%d] = %d\n", i, c); } return; } int main() { write_shm(); read_shm(); return 0; }
//Posix共有メモリを用いたメモリマップファイル上の //カウンタ増加 #include <sys/mman.h> #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <semaphore.h> #define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH) struct shmstruct { int count; }; sem_t *mutex; void init() { int fd; struct shmstruct *ptr; shm_unlink("/posix_shm"); fd = shm_open("/posix_shm", O_RDWR|O_CREAT|O_EXCL, FILE_MODE); ftruncate(fd, sizeof(struct shmstruct)); ptr = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); close(fd); sem_unlink("/sem"); mutex = sem_open("/sem", O_CREAT|O_EXCL, FILE_MODE, 1); sem_close(mutex); } int main() { init(); int fd, i, nloop; pid_t pid; struct shmstruct *ptr; nloop = 1000; fd = shm_open("/posix_shm", O_RDWR, FILE_MODE); ptr = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); close(fd); mutex = sem_open("/sem", 0); pid = getpid(); for (i = 0; i < nloop; i++) { sem_wait(mutex); printf("pid %ld: %d\n", (long)pid, ptr->count++); sem_post(mutex); } return 0; }