Linux---信号量

信号量:

信号量是通过控制通信资源,负责数据的互斥与同步功能实现进程间通信;
信号量本身是一个描述临界资源中资源数目的计数器,防止两个执行流同时访问同一个临界资源,导致数据不一致问题;
当一个信号量的取值非0即1的时候,则称这个信号量是二元信号量;
信号量最常见的操作是P V操作:

P操作:计数器减一,表明对应申请者申请到资源;
V操作:计数器加一,表明用户归还资源。

信号量值S:
S>0:表明有可用资源,并且S表示可用资源的数目;
S=0:表示没有可用资源,也没有进程等待;
S<0:|S|表示在等待队列中进程的个数。

信号量的创建:
int semget(key_t key,int nsems,int semflg)

参数:key:信号量标识;
nsems:信号量集中信号量的个数;
semflg:权限标准。
返回值:成功返回信号量集标识码,失败返回-1.

信号量集的控制
int semctl(int semid,int semnum;int cmd,...)

参数:semid:由semget返回的信号量集标识;
semnum:信号量集中信号量的序号
cmd:对信号量集将要采取的动作。

SETVAL:设置信号量集中的信号量的计数值,(可以对信号进行初始化);
GETVAL:获取信号量集中的信号量的计数值;
IPC_STAT:把semid_ds结构中的数据设置为信号集的当前关联值;
IPC_SET:在进程有足够的权限的前提下,把信号量的当前关联值设置为semid_ds数据结构中给出的值。
IPC_RMID:删除信号集。

…:根据操作的不同而不同,可以自定义
返回值:成功返回0,失败返回-1.

信号量集的创建和访问
int semop(int semid,struct sembuf* sops,unsigned nops)

参数:semid:信号量集的标识;
sops:指向一个信号量结构体指针

struct sembuf
{
short sem_num;//信号量编号
short sem_op;//信号量一次PV操作所加减的数值
short sem_flg;//可缺省,可取IPC_NOWAIT或SEM_UNDO
}

nops:信号量的个数
返回值:成功返回0,失败返回-1.

信号量测试:

//comm.h
#ifndef _COMM_H_
#define _COMM_H_

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

#define PATHNAME "."
#define PROJ_ID 0x6666

union semun
{
        int val;
        struct semid_ds* buf;
        unsigned short* array;
        struct seminfo* _buf;
};

int creatSem(int nums);
int getSem(int nums);
int initSem(int semid,int num,int _val);
int destorySem(int semid);
int P(int semid,int num);
int V(int semid,int num);

#endif
//comm.c
#include"comm.h"

static int Sem(int nums,int flags)
{
        key_t key=ftok(PATHNAME,PROJ_ID);
        if(key<0){
                perror("ftok");
                exit(1);
        }
        int semid=semget(key,nums,flags);
        if(semid<0){
                perror("semget");
                exit(1);
        }
        return semid;
}

int creatSem(int nums)
{
        return Sem(nums,IPC_CREAT|IPC_EXCL|0666);
}
int getSem(int nums)
{
        return Sem(nums,IPC_CREAT);
}
int initSem(int semid,int num,int _val)
{
        union semun _un;
        _un.val=_val;
        if(semctl(semid,num,SETVAL,_un)<0){
                perror("semctl");
                exit(1);
        }
        return 0;
}

int destorySem(int semid)
{
        if(semctl(semid,0,IPC_RMID)<0){
                perror("semctl");
                exit(1);
        }
        return 0;
}

static int PV(int semid,int num,int op)
{
        struct sembuf _sf;
        _sf.sem_num=num;
        _sf.sem_op=op;
        _sf.sem_flg=0;
        if(semop(semid,&_sf,1)<0){
                perror("semop");
                exit(1);

        }
        return 0;  
}

int P(int semid,int num)
{
        return PV(semid,num,-1);
}

int V(int semid,int num)
{
        return PV(semid,num,1);
}
//testSem.c
#include"comm.h"

int main()
{
        int semid=creatSem(1);
        initSem(semid,0,1);

        key_t pid=fork();
        if(pid==0){
                while(1){
                        int _semid=getSem(0);
                        P(_semid,0);
                        printf("S");
                        sleep(1);
                        fflush(stdout);
                        printf("S ");
                        sleep(1);
                        fflush(stdout);
                        V(_semid,0);
                }
        }else if(pid>0){
                while(1){
                        P(semid,0);
                        printf("L");
                        sleep(1);
                        fflush(stdout);
                        printf("L ");
                        sleep(1);
                        fflush(stdout);
                        V(semid,0);
                }
 }
        destorySem(semid);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值