Linux信号量

什么是信号量?

  • 用于实现进程间的互斥与同步的一种方法

理解

  • 比喻一个场景:
    • 一个房间有一把钥匙,有一个人拿了这把钥匙进了这个房间,第二个人想进这个房间而没有钥匙只能等待,等到房间里的人出来(把钥匙拿出来),第二个人拿到钥匙才能进入这个房间
      • 这其中钥匙就是信号量
      • 房间就是临界资源
        • 信号量可以对临界资源进行管控(可以具体到进程间共享内存通信:A进程在往内存写,B不知道A在写,如果A在写B也写就会造成错乱)

特点

  • (p操作:拿锁,,,v操作:放回锁)
    • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
    • 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作
    • 每次对信号量的PV操作不仅限于对信号量值加1或减1,而且可以加减任意正整数
    • 支持信号量组(Linux操作系统中不止一个信号量)

所使用函数原型

  • 使用案例
#include<stdio.h>
#include<sys/sem.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include <unistd.h>
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) */
};
/*int semget(key_t key, int nsems, int semflg);
  key_t key :键值
  int nsems :信号量合集中有几个信号量
  int semflg:权限
*/
/*int semctl(int semid, int semnum, int cmd, ...);
  int semid :信号量ID
  int semnum:操作第几个信号量
  int cmd   :设置信号量为
            :第四个参数是一个联合体
*/
/*int semop(int semid, struct sembuf *sops, size_t nsops);对信号量组进行操作
  int semid          :信号量ID
  struct sembuf *sops:传入信号量集,可以是多个
  size_t nsops       :是第三个参数的个数
*/
void pAction(int id)//拿钥匙
{
   //struct sembuf set[i];多个信号量级
    struct sembuf set;
    set.sem_num = 0;        //信号量编号,默认是0
    set.sem_op  =-1;        //拿钥匙后,钥匙-1
    set.sem_flg =SEM_UNDO;  //没有钥匙时等待模式
    semop(id,&set,1);       //
}
void vAction(int id)//放钥匙
{
    struct sembuf set;
    set.sem_num = 0;
    set.sem_op  = 1;        //拿到就+1
    set.sem_flg =SEM_UNDO;
    semop(id,&set,1);
}
int main(int argv ,char **argc)
{
    key_t key;
    int semid;

    key = ftok(".",2);

    semid = semget(key,1,IPC_CREAT|0666);//获取/创建信号量
    
    union semun initem;
    initem.val = 0;//锁初始化为0

    semctl(semid,0,SETVAL,initem);
    int pid =fork();
    if(pid>0){
        pAction(semid);//拿不到就等带
        printf("Taked ok\n");
        vAction(semid);
        semctl(semid,0,IPC_RMID);//销毁锁
    }
    else if(pid==0){ //父进程拿不到钥匙,所以子进程先运行
        printf("Put ok\n");
        vAction(semid);//放钥匙
    }
    else{
        printf("fork error\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Trt_ToHoldOn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值