セマフォの使い方

Linuxで、C言語を用いてセマフォを活用する方法を、記述します。

セマフォとは、プロセスやスレッドの同時実行を制御するための、OSで用意された機構です。あらかじめ同時実行できる数を指定し、それをセマフォの値の初期値とします(初期値が1の場合は、ほぼミューテックスと等しい動作になります)。セマフォによって同時実行が制限される処理を実行する場合、プロセスはセマフォから実行権を貰います。これをP操作と言います。逆に実行権を返すことをV操作と言います、もし他のプロセスによって、全ての実行権が取られていた場合は、他のプロセスのV操作により、自プロセスがP操作が出来るようになるまで待ちます。

ちなみにLinuxには、SystemVとPOSIXのセマフォがあり、両者は別物ですので、注意して下さい。両者の差異は勉強中です。(プロセス単位、スレッド単位?)

以下の例は、acceptor内で任意の数の子プロセスを生成し、子プロセスがtransport内の処理を実行するものです。transport内の処理を逐次処理とするために、セマフォを使用しております。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define PROCESS_MAX 5

// semctlのコマンド用(開発者がソース内で定義しなくては駄目)
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *_buf;
};

void transport(int sem) {
    int res = 0;
    struct sembuf semb; // semop へ渡す設定内容の構造体

    semb.sem_num = 0;
    semb.sem_op = -1; // セマフォから権限を取得する
    semb.sem_flg = SEM_UNDO;
    res = semop(sem, &semb, 1);

    printf("tansport started\n");
    sleep(2);
    printf("tansport finished\n");

    semb.sem_num = 0;
    semb.sem_op = 1; // セマフォから得た権限を返還する
    semb.sem_flg = SEM_UNDO;
    res = semop(sem, &semb, 1);
}

void acceptor() {
    int res = 0;
    int i = 0;
    int sem;
    union semun semcmd; // semctl へ渡すコマンド用の共用体

    // セマフォを取得する
    sem = semget(IPC_PRIVATE, 1, 0666|IPC_CREAT);

    // セマフォに初期値を設定する(この値が、同時実行を許可する数になる)
    semcmd.val = 1;
    res = semctl(sem, 0, SETVAL, semcmd);

    while(i < PROCESS_MAX) {
        int pid;

        pid = fork(); // fork システムコールで、子プロセス生成
        switch(pid) {
            case 0: // 子プロセスの場合に実行する
                transport(sem);
                exit(0); // 子プロセスはここで終了する
            break;
        }
        // 親プロセスは処理を続行する

        i++;
    }
}

int main() {
    acceptor();
}

本来は、acceptorの中で、前の子プロセスによるtransport処理が終了するまで、fork()システムコールの実行を待ち合わせるようにしたかったのですが、セマフォ操作を実行するプロセスが異なると、様々な制約が発生し、難しくなります。ある意味セマフォは一般的な同期処理を行なうために、安全な手法を提供してくれるのかもしれませんが、少し凝ったことを考えると、使いにくい印象を受けました。それこそ、共有メモリを使った方が、開発者の管理責任は増すものの、明らかに自由度は高くなります。

とにかく今回二日ほど試行してみて感じたことは、セマフォは特定処理の排他制御以外への利用は、なかなか難しいということです。


履歴


トップ   編集 凍結解除 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2005-09-05 (月) 00:57:02