semExample.c(linux下信號量使用實例)

/*
 *Author:
 *Filename: semExample.h
 *Description: 提供信號量的函數調用接口
 */
#ifndef SEMEXAMPLE_H
#define SEMEXAMPLE_H




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

union semun {
    int              val;              /*for SETVAL*/
    struct semid_ds   *buf;            /*for IPC_STAT and IPC_SET*/
    unsigned short    *array;          /*for GETALL and SETALL*/
};



/*
 *Name: init_sem()
 *Function: 信號量的初始化
 *Arguement: 第一個參數爲信號量的標誌符,第二個參數爲初始值
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int init_sem(int sem_mid,int init_value);


/*
 *Name: delete_sem()
 *Function: 信號量的刪除
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int delete_sem(int sem_mid);



/*
 *Name: voperation_sem()
 *Function: 信號量的v操作,使信號量的值加1
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int voperation_sem(int sem_mid);




/*
 *Name: poperation_sem()
 *Function: 信號量的p操作,使信號量的值減1,該部分代碼與信號量的v操作代碼類似
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int poperation_sem(int sem_mid);


#endif




/********************************************************************************************************************************************************************/

/*
 *Author:
 *Filename: semExample.c
 *Description: 因爲信號量的函數調用接口負責,所以通常將信號量的函數封裝成一些額基本函數供調用。
 */


#include "semExample.h"


/*
 *Name: init_sem()
 *Function: 信號量的初始化
 *Arguement: 第一個參數爲信號量的標誌符,第二個參數爲初始值
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int init_sem(int sem_mid,int init_value)
{
//使用semctl函數來爲信號量進行初始化
union semun sem_union;
/*
union semun
    {
        int val;//使用SETVAL的值
        struct semid_ds *buf;    //使用IPC_STAT,IPC_SET的buf
        unisgned short *array;    //使用GETALL,SETALL的數組
    }
*/


sem_union.val = init_value;
if(semctl(sem_mid,0,SETVAL,sem_union) == -1)
{
perror("Init_sem error");
return -1;
}
return 0;
}






/*
 *Name: delete_sem()
 *Function: 信號量的刪除
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int delete_sem(int sem_mid)
{
//使用sem_ct函數,命令參數設爲IPC_RMID
union semun sem_union;
if(semctl(sem_mid,0,IPC_RMID,sem_union) == -1)
{
perror("Delete_sem error");
return -1;
}
return 0;
}




/*
 *Name: voperation_sem()
 *Function: 信號量的v操作,使信號量的值加1
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int voperation_sem(int sem_mid)
{
/*調用semop函數:int semop(int semid, struct sembuf *sops, unsigned nsops);
struct sembuf
{
        unsigned short sem_num;
        short sem_op;
        short sem_flg;
}
*/
struct sembuf sem_a;
//單個信號量的V操作
sem_a.sem_num = 0;
sem_a.sem_op = 1;
//該標誌表明,在系統退出後,自動釋放該信號量
sem_a.sem_flg = SEM_UNDO;
if(semop(sem_mid,&sem_a,1) == -1)
{
perror("voperation_sem error");
return -1;
}
return 0;
}




/*
 *Name: poperation_sem()
 *Function: 信號量的p操作,使信號量的值減1,該部分代碼與信號量的v操作代碼類似
 *Arguement: 參數爲信號量的標誌符
 *Returnvalue:  出錯返回-1,成功返回0.
 */


int poperation_sem(int sem_mid)
{
/*調用semop函數:int semop(int semid, struct sembuf *sops, unsigned nsops);
struct sembuf
{
        unsigned short sem_num;
        short sem_op;
        short sem_flg;
}
*/
struct sembuf sem_a;
//單個信號量的V操作
sem_a.sem_num = 0;
sem_a.sem_op = -1;
//該標誌表明,在系統退出後,自動釋放該信號量
sem_a.sem_flg = SEM_UNDO;
if(semop(sem_mid,&sem_a,1) == -1)
{
perror("voperation_sem error");
return -1;
}
return 0;
}



/********************************************************************************************************************************************************************/

/*
 *Author:
 *Filename: main.c
 *Description: 利用fork函數創建父子進程,利用信號量函數來解決同布與互斥問題。
 */




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


int main()
{
pid_t pid;
int sem_id;

//調用semget函數獲得信號量標誌符
sem_id = semget((key_t)1234,1,0666|IPC_CREAT);
if(sem_id == -1)
{
perror("semget error");
exit(-1);
}
//初始化信號量值爲0
init_sem(sem_id,0);
//fork函數創建子進程
pid = fork();
if(pid == -1)
{
perror("fork error");
exit(-1);
}
else if(pid == 0)//進入子進程
{
printf("I am child process,i am working\n");
sleep(5);
voperation_sem(sem_id);//v操作對信號量+1
}
else
{
poperation_sem(sem_id);//P操作對信號量-1
printf("I am parent process.\n");
voperation_sem(sem_id);//v操作對信號量+1
delete_sem(sem_id);
}
exit(0);


}



結果:

說明,在使用信號量時,只能由一個進程來完成操作後,另一個進程才能獲得信號量進行操作。

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