タイマー割り込みの作り方(セマフォを使う)


次はfork()とセマフォを使ったサンプルです。
ソースは以下のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <time.h>
#include <signal.h>

int semid;

//排他処理の開始するためのロック
//自分よりも先にロックされていた場合にはロック解除されるまでスリープします
void lock(int semid){
    struct sembuf sb[1];
    sb[0].sem_num=0;
    sb[0].sem_op=-1;
    sb[0].sem_flg=0;
    if(EOF==semop(semid,sb,1)){
        printf("%s\n","lock ERR");
        exit(1);
    }
}
//排他処理の終了のためのロック解除
void unlock(int semid){
    struct sembuf sb[1];
    sb[0].sem_num=0;
    sb[0].sem_op=1;
    sb[0].sem_flg=0;
    if(EOF==semop(semid,sb,1)){
        printf("%s\n","unlock ERR");
        exit(1);
    }
}

int main(int argc, char **argv) {
    int i=1;
    pid_t result_pid;
    int kill_status;
    int wait_status;
    union semun {
        int              val;     /* SETVAL の値 */
        struct semid_ds  *buf;    /* IPC_STAT, IPC_SET 用のバッファ */
        unsigned short   *array;  /* GETALL, SETALL 用の配列 */
    } ctl_arg;
    time_t now;
    struct tm *pnow;

    //セマフォを割り付けます
    semid=semget(IPC_PRIVATE,1,0666);
    if(semid==EOF){
        printf("%s\n","semget ERR");
        exit(1);
    }
    //セマフォに初期値を書き込みます
    ctl_arg.val = 1;
    if((semctl(semid,0,SETVAL,ctl_arg))==EOF){
        printf("%s\n","semctl ERR");
        exit(1);
    }

    result_pid = fork();
    if (result_pid == 0) {
    // 子プロセス開始 //
    // 1秒毎にセマフォをunlockする
        while (1) {
            sleep(1);
            unlock(semid);
        }
    }

    for(i=0;i<60;i++) {
        lock(semid); // Wait Unlock
        now = time(NULL);
        pnow = localtime(&now);
        printf("%d:%d:%d\n",pnow->tm_hour,pnow->tm_min,pnow->tm_sec);
    }

    //子プロセスをKILL
    kill_status = kill( result_pid, SIGKILL );
    wait(&wait_status);

    //セマフォの削除
    if((semctl(semid,0,IPC_RMID,0))==EOF){
        printf("%s\n","ERR");
        exit(1);
    }

    exit(0);
}

実行結果は前回と同じになりますが、メイン処理はsleep()を使わずに、
セマフォーの解除待ちなので、平行してボタン入力などの割り込み処理を行うことができます。

続く