您的位置:首页 > 运维架构 > Linux

信号量(sem)

2016-07-28 18:12 513 查看
代码:

comm.h:

#ifndef _MYSEM_
#define _MYSEM_
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define _PATH_ "."
#define _PROJ_ID_ 0x0603

typedef union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
}semun_t;

int create_sem(int nsems);
int get_sem(int nsems);
int init_sem(int sem_id,int which,int init_val);
int p_sem(int sem_id,unsigned short which);//-1
int v_sem(int sem_id,unsigned short which);//+1
int destroy_sem(int sem_id);

#endif


comm.c:
#include "comm.h"

static int com_sem(int nsems,int flag)
{
key_t key = ftok(_PATH_,_PROJ_ID_);
if( key < 0 ){
perror("ftok");
return -1;
}
int sem_id = semget(key,nsems,flag);//创建信号量
if(sem_id < 0){
perror("semget");
return -2;
}
return sem_id;
}
int creat_sem(int nsems)
{
int flag = IPC_CREAT | IPC_EXCL | 0666;
return com_sem(nsems,flag);
}
int get_sem(int nsems)
{
int flag = IPC_CREAT;
return com_sem(nsems,flag);
}
static int com_semop(int sem_id,unsigned short which,short op)
{//对哪个信号量集中的哪一个信号进行op指定的操作
struct sembuf semb[1];//只考虑二元信号量,所以只有一个元素
semb[0].sem_num = which;
semb[0].sem_op = op;//进行什么操作是由op说了算
semb[0].sem_flg = 0;//UNDO,若一个进程在临界区崩溃了,那么flag就维护信号量,把信号量恢复
if(semop(sem_id,semb,1) < 0)
{
perror("semop");
return -1;
}
return 0;
}
int p_sem(int sem_id,unsigned short which)
{//进行p操作
int op = -1;
return com_semop(sem_id,which,op);
}
int v_sem(int sem_id,unsigned short which)
{//进行v操作
int op = 1;
return com_semop(sem_id,which,op);
}
int init_sem(int sem_id,int which,int init_val)
{
semun_t sem_val;
sem_val.val = init_val;
int ret = semctl(sem_id,which,SETVAL,sem_val);//初始化信号量
if(ret < 0)
{
perror("semct");
return -1;
}
return 0;
}
int destory_sem(int sem_id)
{
int ret = semctl(sem_id,0,IPC_RMID);//0是指定的信号量,此处讨论的是二元信号量
if(ret < 0){
perror("semctl");
return -1;
}
printf("\ndestroy success\n");
return 0;
}sem_stdout.c:(父子进程互斥访问stdout)
#include "comm.h"

int main()
{
int f_sem_id = creat_sem(1);//使用互斥信号量(二元信号量)父进程先获取信号量
init_sem(f_sem_id,0,1);//信号量从下标0开始,被初始化为1
pid_t id = fork();
if( id == 0)
{//child
int c_sem_id = get_sem(1);
int count = 3;
while(1)
{
p_sem(c_sem_id,0);//对第一个信号量进行P操作
printf("A");
fflush(stdout);
sleep(rand()%3);
printf("A");
fflush(stdout);
sleep(rand()%3);
v_sem(c_sem_id,0);//对第一个信号量进行V操作
count--;
if(count == 0){
break;
}
}
}
else
{//father
int count = 3;
while(1)
{
p_sem(f_sem_id,0);
printf("B");
fflush(stdout);
sleep(rand()%3);
printf("B");
fflush(stdout);
sleep(rand()%3);
v_sem(f_sem_id,0);
count--;
if(count == 0){
break;
}
}
}
//sleep(3);
wait(NULL);
destory_sem(f_sem_id);
return 0;
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux