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;
}