进程通信之信号量

信号量

信号量是一个计数器,用来表示系统资源的数量,信号量用于多进程对共享数据对象的访问,来实现程序的同步互斥。为了正确实现信号量,信号量的加减操作必须是原子操作,因此,信号量也是在内核中实现的。


先看一下同步互斥和原子操作:

同步互斥

互斥
一个进程占用资源,其它进程就不能使用该资源,进程间的这种关系为进程互斥
这些只能被一个进程同时使用的资源被称为临界资源
进程中访问临界资源的一段需要互斥执行的代码称为临界区
访问临界区的条件是临界资源没有被占用。

举个例子:假如厕所只有一个坑,一个人蹲上了,那么其他的人就不能再蹲了,这个坑就是临界资源。

同步
当进程A的执行依赖进程B的执行结果时,进程之间的执行必须存在一定的顺序关系,这种关系称为进程的同步

原子操作

原子操作是指一次不存在任何中断和失败的操作,要么操作成功,要么操作没有执行,不存在部分执行的状态。
在此概念产生的那个年代,物理学的最小单位还是原子,因此这里原子是指不可在分割的整体。


信号量和 P、V原语

P、V操作
假设用S表示资源数的个数,P、V操作分别表示对S的减和加操作

  • P()操作(Prolaag,荷兰语减少)
    • S减n,表示可用资源数减少
    • 如果S<0,进入等待,否则继续
  • V()操作(Verhoog,荷兰语增加)
    • S加n,表示可用的资源数增加
    • 如果s>=0,则唤醒一个等待中的进程

信号量的伪代码实现

struct semaphore
{
    int value;
    pointer_PCB queue;
};

P原语

P(s)
{
    s.value = s.value--;
    if (s.value < 0)
    {
        //该进程状态置为等待状状态
        //将该进程的PCB插入相应的等待队列s.queue末尾
    }
}

V原语

V(s)
{
    s.value = s.value++;
    if (s.value < =0)
    {
        //唤醒相应等待队列s.queue中等待的一个进程
        //改变其状态为就绪态
        //并将其插入就绪队列
    }
}

信号量相关函数
  • semget函数

    • 功能
      • 用来创建和访问一个信号量集
    • 原型
      • int semget(key_t key, int nsems, int semflg);
    • 参数
      • key–信号集的名字
      • nsems–信号集中信号的个数
      • semflg–九个权限标志构成
    • 返回值

      • 成功返回一个非负数,表示信号集的表示id,失败返回-1。

  • shmctl函数

    • 功能
      • 用于控制信号量集
    • 原型
      • int semctl(int semid, int semnum, int cmd, ...);
    • 参数
      • semid–由semget函数返回的信号标识id
      • semnum–信号集中信号量的序号
      • cmd–将要采取的动作
    • 返回值

      • 成功返回0,失败返回-1

  • semop函数

    • 功能
      • 用来创建和访问一个信号量集
    • 原型
      • int semop(int semid, struct sembuf *sops, unsigned nsops);
    • 参数
      • semid–信号量标识id
      • sops–指向一个结构数值的指针
      • nsops–信号量个数
    • 返回值
      • 成功返回0,失败返回-1
    • sembuf结构体

      struct sembuf 
      {
           short sem_num;
           short sem_op;
           short sem_flg;
      };
      • sem_num–信号量的编号
      • sem_op–信号量一次PV操作时加减的数值,一般只会用到两个值(-1和1)分别标识减1和加1
      • sem_flag–两个取值为IPC_NOWAIT或SEM_UNDO
相关指令
  • ipcs -s
    • 列出当前信号量信息
  • ipcrm -s semid
    • 删除id为semid的信号量,一般由创建它的进程删除,不需要手动删除
代码实现

信号量的代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值