2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ セマフォ動作確認

Last updated at Posted at 2018-08-01

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.

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?