/* * Copyright (C) NAKAMURA Minoru */ #include #include #include #include #include #include #include #include #include enum { /* 適当なサイズに */ SHARED_SIZE = 16 * 1024 }; typedef struct { pthread_mutexattr_t mutex_attr; pthread_mutex_t mutex; } shared_data_t; static shared_data_t* shared_data_p; /** * 共有メモリを準備 */ void* allocate_shared_memory(void) { int i, fd; void* p = 0; size_t t; char filename[] = "/tmp/tmpfileXXXXXX"; // 一時ファイルをオープンして、ファイルは削除 fd = mkstemp(filename); if (fd == -1) { perror("mkstemp"), exit(1); } unlink(filename); // mmap 前にファイルにダミーデータを書き込み t = 0; while (t < SHARED_SIZE) { char buffer[1024]; t += write(fd, buffer, sizeof(buffer)); } // mmap p = mmap(0, SHARED_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { perror("mmap"), exit(1); } close(fd); // 確認のため memory-mmaped file をゼロクリア for (i=0 ; imutex_attr)) { perror("pthread_mutexattr_init"), exit(1); } if (pthread_mutexattr_setpshared(&shared_data_p->mutex_attr, PTHREAD_PROCESS_SHARED)) { perror("pthread_mutexattr_setpshared"), exit(1); } if (pthread_mutex_init(&shared_data_p->mutex, &shared_data_p->mutex_attr)) { perror("pthread_mutex_init"), exit(1); } if (fork() == 0) { // 子プロセス1を作成して mutex をロックさせたまま突然死させる pthread_mutex_lock(&shared_data_p->mutex); printf("Process %d is terminated while the mutex is locking.\n", getpid()); // 子プロセス2が起動するまでのタイミング合わせ sleep(1); abort(); } sched_yield(); if (fork() == 0) { // 子プロセス2を作成して mutex をロックする // 子プロセス1が mutex をロックしているので最初はブロックされる。 pthread_mutex_lock(&shared_data_p->mutex); printf("Process %d succeed acquring the mutex.\n", getpid()); pthread_mutex_unlock(&shared_data_p->mutex); exit(0); } // 子プロセス1が異常終了するのを待つ sleep(2); // mutex を無理矢理アンロック pthread_mutex_unlock(&shared_data_p->mutex); sleep(2); return 0; }