Linux信號量的使用

實現代碼

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>

static int set_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static void del_sem_set(void);

/* 定義自己的semun聯合體*/
union semun {
    int                 val;
    struct semid_ds     *buf;
    unsigned short      *array;
    struct seminfo      *__buf;
};

/* 定義全局變量sem_id保存信號量集的標識符*/
static int sem_id;

int main()
{
    int i;
    pid_t pid;
    char ch;

    /* 創建信號量集*/
    sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);	
    if(sem_id == -1) {
        fprintf(stderr, "Failed to create semaphore set. \n");
        exit(EXIT_FAILURE);
    }
    if(!set_semvalue()) {	        /* 設置信號量的值*/
        fprintf(stderr, "Failed to initialize semaphore\n");
        exit(EXIT_FAILURE);
    }

    pid = fork();				    /* 創建子進程*/
    switch(pid)
    {
    case -1:
        perror("fork failed");
        exit(EXIT_FAILURE);
    case 0:						    /* 子進程*/
        ch = 'c';
        break;
    default:						/* 父進程*/
        ch = 'p';
        break;
    }

    for(i=0; i < 5; i++){		    /* 使用信號量控制*/
        // semaphore_p();			    /* P操作,獲取信號量*/
        printf("%c", ch);		    /* 在父進程中輸出X,在子進程中輸出O */
        fflush(stdout);
        sleep(1);
        // semaphore_v();			    /* V操作,釋放信號量*/
    }

    if(pid > 0) {				    /* 父進程*/
        wait(NULL);				    /* 等待子進程退出*/
        del_sem_set();			    /* 刪除信號量集*/
    }

    printf("PID%d - finished", getpid());
    exit(EXIT_SUCCESS);
}

/* 設置信號量的值*/
static int set_semvalue(void)
{
    union semun sem_union;

    sem_union.val = 1;
    if(semctl(sem_id, 0, SETVAL, sem_union) == -1)
        return 0;

    return 1;
}

/* P操作,獲取信號量*/
static int semaphore_p(void)
{
    struct sembuf sem_b;

    sem_b.sem_num  = 0;
    sem_b.sem_op   = -1;
    sem_b.sem_flg  = SEM_UNDO;
    if(semop(sem_id, &sem_b, 1) == -1) {
        fprintf(stderr, "semaphore_p failed/n");
        return 0;
    }

    return 1;
}

/* V操作,釋放信號量*/
static int semaphore_v(void)
{
    struct sembuf sem_b;

    sem_b.sem_num  = 0;
    sem_b.sem_op   = 1;
    sem_b.sem_flg  = SEM_UNDO;
    if(semop(sem_id, &sem_b, 1) == -1) {
        fprintf(stderr, "semaphore_v failed/n");
        return 0;
    }

    return 1;
}

/* 刪除信號量集*/
static void del_sem_set(void)
{
    union semun sem_union;

    if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
        fprintf(stderr, "Failed to delete semaphore/n");
}

運行結果

pcpcpcpcpc
PID15974 - finished 
PID15973 - finished

分析:因爲在進程調用的主函數中相關程序段使用了信號量控制,所以在程序執行過程中各進程對這一程序段是互斥訪問的,一個進程執行完後另一個進程開始執行。

修改程序

在主程序中註釋掉“semaphore_p()”和“semaphore_v()”兩處語句,觀察實驗結果。

for(i=0; i < 5; i++){           /* 使用信號量控制*/
    // semaphore_p();               /* P操作,獲取信號量*/
    printf("%c", ch);           /* 在父進程中輸出X,在子進程中輸出O */
    fflush(stdout);
    sleep(1);
    // semaphore_v();               /* V操作,釋放信號量*/
}

運行結果

pccppcpccp
PID16071 - finished
PID16070 - finished

分析:沒有使用信號量控制,循環打印語句的執行結果不確定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章