C++のセマフォの値の増減が行われているか
確認するためのプログラム
wait
while(1)でループ
「end」と入力されるまで終わらない。
また、wait...[]←この部分にセマフォの値を表示した。
3つpostしても2の表示になるのは、
1つ目は、waitから復帰して動くためである
sem_wait.cpp
# include <iostream>
using namespace std;
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <pthread.h>
# include <semaphore.h>
# include <sys/wait.h>
# include <unistd.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/stat.h>
# define SEMNAME "/sem"
# define STRNAME "/string"
# define MAX 1024
// sem開放
void sem_free(sem_t *sem){
// semaphore解放
sem_destroy( sem );
// 共有メモリ開放
shm_unlink(SEMNAME);
}
// str開放
void str_free(char *str){
// 共有メモリ開放
shm_unlink(STRNAME);
}
int main()
{
int p_id;
int status;
int return_code = 0;
int i;
int fd_sem;
void *ptr_sem;
int sem_num;
int fd_str;
void *ptr_str;
struct stat stat;
// semの共有メモリ作成
fd_sem = shm_open(SEMNAME, O_CREAT | O_RDWR, 0666);
ftruncate(fd_sem, MAX);
// semの共有メモリをポインタに割り当てる
ptr_sem = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_sem, 0);
// strの共有メモリ作成
fd_str = shm_open(STRNAME, O_CREAT | O_RDWR, 0666);
ftruncate(fd_str, MAX);
// strの共有メモリをポインタに割り当てる
ptr_str = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_str, 0);
// semのポインタのアドレスをsemに割り当てる
sem_t *sem = (sem_t*)ptr_sem;
// strのポインタのアドレスをstrに割り当てる
char *str = (char*)ptr_str;
// sempahoreの初期化:プロセス間を可能でsemの値0から
if (sem_init( sem, 1, 0 ) < 0) {
perror("init");
sem_free(sem);
exit(EXIT_FAILURE);
}
strcpy(str,"Initial");
cout << str << endl;
while(1){
sem_getvalue(sem, &sem_num);
cout << "wait...[" << sem_num << "]" << endl;
if(sem_wait(sem) < 0){ // waitする
perror("wait");
sem_free(sem);
exit(EXIT_FAILURE);
}
if(strcmp(str, "end\n") == 0){
break;
}
cout << "> " << str;
sleep(1);
}
cout << "end" << endl;
if (sem_post(sem) < 0) { // postする
perror("post");
sem_free(sem);
exit(EXIT_FAILURE);
}
sem_free(sem);
str_free(str);
return return_code;
}
post
post側でもwhile(1)のループ処理で
「end」の入力が来るまで終わらない。
セマフォの挙動を確認するために
一度文字列を書いた後、3回postするので
wait側は、3回同じ文字列が表示される
sem_post.cpp
# include <iostream>
using namespace std;
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <pthread.h>
# include <semaphore.h>
# include <sys/wait.h>
# include <unistd.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/stat.h>
# define SEMNAME "/sem"
# define STRNAME "/string"
// sem開放
void sem_free(sem_t *sem){
// semaphore解放
sem_destroy( sem );
// 共有メモリ開放
shm_unlink(SEMNAME);
}
// str開放
void str_free(char *str){
// 共有メモリ開放
shm_unlink(STRNAME);
}
int main()
{
int p_id;
int status;
int return_code = 0;
int i;
int fd_sem;
void *ptr_sem;
int sem_num;
int fd_str;
void *ptr_str;
struct stat stat;
// semの共有メモリ作成
fd_sem = shm_open(SEMNAME, O_CREAT | O_RDWR, 0666);
ftruncate(fd_sem, 1024);
// semの共有メモリをポインタに割り当てる
ptr_sem = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_sem, 0);
// strの共有メモリ作成
fd_str = shm_open(STRNAME, O_CREAT | O_RDWR, 0666);
ftruncate(fd_str, 1024);
// strの共有メモリをポインタに割り当てる
ptr_str = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_str, 0);
// semのポインタのアドレスをsemに割り当てる
sem_t *sem = (sem_t*)ptr_sem;
// strのポインタのアドレスをstrに割り当てる
char *str = (char*)ptr_str;
// sempahoreの初期化:プロセス間を可能でsemの値0から
if (sem_init( sem, 1, 0 ) < 0) {
perror("init");
sem_free(sem);
exit(EXIT_FAILURE);
}
strcpy(str,"Initial");
cout << str << endl;
while(1){
sem_getvalue(sem, &sem_num);
cout << "wait...[" << sem_num << "]" << endl;
if(sem_wait(sem) < 0){ // waitする
perror("wait");
sem_free(sem);
exit(EXIT_FAILURE);
}
if(strcmp(str, "end\n") == 0){
break;
}
cout << "> " << str;
sleep(1);
}
cout << "end" << endl;
if (sem_post(sem) < 0) { // postする
perror("post");
sem_free(sem);
exit(EXIT_FAILURE);
}
sem_free(sem);
str_free(str);
return return_code;
}
実行結果
コンパイル
❯ g++ sem_wait2.cpp -pthread -lrt -o w.o
❯ g++ sem_post2.cpp -pthread -lrt -o p.o
wait側の結果
❯ ./w.o
Initial
wait...[0]
> aaaaa
wait...[2]
> aaaaa
wait...[1]
> aaaaa
wait...[0]
end
post側の結果
❯ ./p.o
str input please...
> aaaaa
str input please...
> end
post done.