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);


}



结果:

说明,在使用信号量时,只能由一个进程来完成操作后,另一个进程才能获得信号量进行操作。

发布了61 篇原创文章 · 获赞 6 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/shayueqing/article/details/11790435
今日推荐