*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);
}
结果:
说明,在使用信号量时,只能由一个进程来完成操作后,另一个进程才能获得信号量进行操作。