*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);
}
結果:
說明,在使用信號量時,只能由一個進程來完成操作後,另一個進程才能獲得信號量進行操作。