共有メモリを取得する最新の方法は、Single UNIX Specification で提供されている API を使用することです。以下は 2 つのプロセスの例です。1 つは共有メモリ オブジェクトを作成して内部にデータを配置し、もう 1 つはそれを読み取ります。
最初のプロセス:
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define SHM_NAME "/test"
typedef struct
{
int item;
} DataItem;
int main (void)
{
int smfd, i;
DataItem *smarr;
size_t size = 20*sizeof(DataItem);
// Create a shared memory object
smfd = shm_open(SHM_NAME, O_RDWR | O_CREAT, 0600);
// Resize to fit
ftruncate(smfd, size);
// Map the object
smarr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, smfd, 0);
// Put in some data
for (i = 0; i < 20; i++)
smarr[i].item = i;
printf("Press Enter to remove the shared memory object\n");
getc(stdin);
// Unmap the object
munmap(smarr, size);
// Close the shared memory object handle
close(smfd);
// Remove the shared memory object
shm_unlink(SHM_NAME);
return 0;
}
このプロセスは、 で共有メモリ オブジェクトを作成しますshm_open()
。オブジェクトは初期サイズ 0 で作成されるため、 を使用して拡大されftruncate()
ます。次に、オブジェクトは、 を使用してプロセスの仮想アドレス空間にメモリ マップされますmmap()
。ここで重要なことは、マッピングが読み取り/書き込み ( PROT_READ | PROT_WRITE
) であり、共有 ( MAP_SHARED
) であることです。マッピングが完了すると、通常の動的に割り当てられたメモリとしてアクセスできます (実際のところmalloc()
、glibc
Linux ではより大きな割り当てに匿名メモリ マッピングを使用します)。次に、プロセスはデータを配列に書き込み、Enter キーが押されるまで待機します。次に、 を使用してオブジェクトのマップmunmap()
を解除し、ファイル ハンドルを閉じて、 でオブジェクトのリンクを解除しますshm_unlink()
。
2 番目のプロセス:
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#define SHM_NAME "/test"
typedef struct
{
int item;
} DataItem;
int main (void)
{
int smfd, i;
DataItem *smarr;
size_t size = 20*sizeof(DataItem);
// Open the shared memory object
smfd = shm_open(SHM_NAME, O_RDONLY, 0600);
// Map the object
smarr = mmap(NULL, size, PROT_READ, MAP_SHARED, smfd, 0);
// Read the data
for (i = 0; i < 20; i++)
printf("Item %d is %d\n", i, smarr[i].item);
// Unmap the object
munmap(smarr, size);
// Close the shared memory object handle
close(smfd);
return 0;
}
これは、共有メモリ オブジェクトを読み取りアクセス専用に開き、読み取りアクセス専用にメモリ マップします。配列の要素に書き込もうとするとsmarr
、セグメンテーション違反が発生します。
最初のプロセスをコンパイルして実行します。次に、別のコンソールで 2 番目のプロセスを実行し、出力を観察します。2 番目のプロセスが終了したら、最初のプロセスに戻り、Enter キーを押して共有メモリ ブロックをクリーンアップします。
詳細については、各関数のマニュアル ページまたは SUS のメモリ管理部分を参照してください (これらの関数のシステム固有の動作が文書化されているため、マニュアル ページを参照することをお勧めします)。