2010-01-26
■[開発日記]
リハビリ(?)に、SysV系の共有メモリ操作のサンプル作成。
共有メモリ ( shmget/shmat/shmdt )
シグナル周りが面倒だったので、SIGTERMを同期ハンドリングする方法で作成しました。
個人的には非同期ハンドリングよりも、デバッグしやすいので、こういう実装を好みます。
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string> int main( int argc, char** argv) { key_t ipc_key = 0x00000500; size_t memsize = 4096; int shmid = -1; bool delete_mode = false; bool writer = false; bool reader = false; bool view_mode = false; int state = 0; for ( int i = 1; i < argc; i++ ) { std::string arg( argv[i] ); if ( state == 0 ) { if ( arg == std::string("-k") ) { state = 1; } else if ( arg == std::string("-s") ) { state = 2; } else if ( arg == std::string("-d") ) { delete_mode = true; } else if ( arg == std::string("-v") ) { view_mode = true; } else if ( arg == std::string("-w") ) { writer = true; } else if ( arg == std::string("-r") ) { reader = true; } } else if ( state == 1 ) { ipc_key = (key_t) strtol( argv[i], NULL, 0 ); state = 0; } else if ( state == 2 ) { memsize = (size_t) strtol( argv[i], NULL, 0 ); state = 0; } } shmid = shmget ( ipc_key, memsize, IPC_CREAT | 0666 ); if ( shmid == -1 ) { perror("shmget"); printf(" key=%x size=%ld mode=%x\n", ipc_key, (long)memsize, IPC_CREAT | 0666 ); return -1; } printf("[create] shmid=%d key=%x size=%ld\n", shmid, ipc_key, (long)memsize ); if ( view_mode ) { struct shmid_ds data_seg; if ( shmctl( shmid, IPC_STAT, &data_seg ) == -1 ) { perror("shmctl"); printf(" shmid=%d cmd=IPC_STAT\n", shmid ); return -1; } printf("[view] shmid=%d\n", shmid ); printf(" shm_segsz=%ld\n", (long)data_seg.shm_segsz ); printf(" shm_atime=%ld\n", (long)data_seg.shm_atime ); printf(" shm_dtime=%ld\n", (long)data_seg.shm_dtime ); printf(" shm_ctime=%ld\n", (long)data_seg.shm_ctime ); printf(" shm_cpid=%d\n", data_seg.shm_cpid ); printf(" shm_lpid=%d\n", data_seg.shm_lpid ); printf(" shm_nattach=%ld\n", (long)data_seg.shm_nattch ); } if ( writer || reader ) { void * shmaddr = NULL; shmaddr = shmat( shmid, NULL, 0 ); if ( shmaddr == (void*)-1 ) { perror("shmat"); printf(" shmid=%d\n", shmid ); return -1; } printf("[attach] shmaddr=%p\n", shmaddr ); sigset_t block_set; sigemptyset( &block_set ); sigaddset ( &block_set, SIGTERM ); sigprocmask( SIG_BLOCK, &block_set, NULL ); srandom( (unsigned int)time(NULL) ); while(true) { sigset_t pend; sigpending(&pend); if ( sigismember( &pend, SIGTERM ) == 1 ) { printf ("[receive] SIGTERM\n"); break; } sleep (1); int* p = (int*)shmaddr; if ( writer ) { int w = random(); printf ("[write] *p = %d\n", w ); *p = w; } if ( reader ) { int r = *p; printf ("[read] *p = %d\n", r ); } } if ( shmdt( shmaddr ) == -1 ) { perror("shmdt"); printf(" shmaddr=%p\n", shmaddr ); } printf("[detach] shmaddr=%p\n", shmaddr ); } if ( delete_mode ) { if ( shmctl( shmid, IPC_RMID, NULL ) == -1 ) { perror("shmctl"); printf(" shmid=%d cmd=IPC_RMID buf=NULL\n", shmid ); } printf("[delete] shmid=%d\n", shmid ); } return 0; }