プロセスでの共有メモリの使用についていくつか質問があります。以前の投稿をいくつか見ましたが、答えを十分に正確に収集できませんでした。よろしくお願いします。
以下のように shm_open + mmap を使用しています。このコードは、親と子が交互に g_shared->count をインクリメントすることで意図したとおりに機能します (同期は移植性がありません。特定のメモリ モデルでのみ機能しますが、今のところ私の場合には十分です)。ただし、MAP_SHARED を MAP_ANONYMOUS | に変更すると、MAP_SHARED、メモリは共有されず、「フラグ」が反転しないため、プログラムがハングします。フラグを削除すると、各プロセスが 0 から 10 までカウントすることで何が起こっているかが確認されます (それぞれが構造体の独自のコピーを持っているため、'count' フィールドがあることを意味します)。これは予想される動作ですか?メモリがファイルによってバックアップされることは望ましくありません。これらがプロセスではなくスレッドである場合に何が起こるかをエミュレートしたいと思っています (他の理由でプロセスである必要があります)。
本当に shm_open が必要ですか? プロセスは同じ階層に属しているので、代わりに mmap だけを使用できますか? 「exec」がなければこれはかなり簡単なことだと理解していますが、「fork」の後に「exec」がある場合、どうすれば機能しますか?
x86_64 (Intel i7-2600) でカーネル バージョン 3.2.0-23 を使用しています。この実装では、mmap は、同じグローバル オブジェクトを共有する pthread を持つ共有メモリと同じ動作 (正確さとパフォーマンス) を提供しますか? たとえば、MMU はセグメントを「キャッシュ可能な」MTRR/TLB 属性でマップしますか?
cleanup_shared() コードは正しいですか? メモリリークはありますか?どうすれば確認できますか?たとえば、System V の「ipcs」に相当するものはありますか?
ありがとう、/Doobs
shmem.h:
#ifndef __SHMEM_H__
#define __SHMEM_H__
//includes
#define LEN 1000
#define ITERS 10
#define SHM_FNAME "/myshm"
typedef struct shmem_obj {
int count;
char buff[LEN];
volatile int flag;
} shmem_t;
extern shmem_t* g_shared;
extern char proc_name[100];
extern int fd;
void cleanup_shared() {
munmap(g_shared, sizeof(shmem_t));
close(fd);
shm_unlink(SHM_FNAME);
}
static inline
void init_shared() {
int oflag;
if (!strcmp(proc_name, "parent")) {
oflag = O_CREAT | O_RDWR;
} else {
oflag = O_RDWR;
}
fd = shm_open(SHM_FNAME, oflag, (S_IREAD | S_IWRITE));
if (fd == -1) {
perror("shm_open");
exit(EXIT_FAILURE);
}
if (ftruncate(fd, sizeof(shmem_t)) == -1) {
perror("ftruncate");
shm_unlink(SHM_FNAME);
exit(EXIT_FAILURE);
}
g_shared = mmap(NULL, sizeof(shmem_t),
(PROT_WRITE | PROT_READ),
MAP_SHARED, fd, 0);
if (g_shared == MAP_FAILED) {
perror("mmap");
cleanup_shared();
exit(EXIT_FAILURE);
}
}
static inline
void proc_write(const char* s) {
fprintf(stderr, "[%s] %s\n", proc_name, s);
}
#endif // __SHMEM_H__
shmem1.c (親プロセス):
#include "shmem.h"
int fd;
shmem_t* g_shared;
char proc_name[100];
void work() {
int i;
for (i = 0; i < ITERS; ++i) {
while (g_shared->flag);
++g_shared->count;
sprintf(g_shared->buff, "%s: %d", proc_name, g_shared->count);
proc_write(g_shared->buff);
g_shared->flag = !g_shared->flag;
}
}
int main(int argc, char* argv[], char* envp[]) {
int status, child;
strcpy(proc_name, "parent");
init_shared(argv);
fprintf(stderr, "Map address is: %p\n", g_shared);
if (child = fork()) {
work();
waitpid(child, &status, 0);
cleanup_shared();
fprintf(stderr, "Parent finished!\n");
} else { /* child executes shmem2 */
execvpe("./shmem2", argv + 2, envp);
}
}
shmem2.c (子プロセス):
#include "shmem.h"
int fd;
shmem_t* g_shared;
char proc_name[100];
void work() {
int i;
for (i = 0; i < ITERS; ++i) {
while (!g_shared->flag);
++g_shared->count;
sprintf(g_shared->buff, "%s: %d", proc_name, g_shared->count);
proc_write(g_shared->buff);
g_shared->flag = !g_shared->flag;
}
}
int main(int argc, char* argv[], char* envp[]) {
int status;
strcpy(proc_name, "child");
init_shared(argv);
fprintf(stderr, "Map address is: %p\n", g_shared);
work();
cleanup_shared();
return 0;
}