Linux进程间通信--信号量

什么是信号量

  • 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个进程访问代码的临界区域。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个进程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
  • 信号量的本质是计数器,信号量里面记录了临界资源的数目,有多少数目,信号量的值就为多少。信号量是一个特殊的变量,进程对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量。信号量值为1的信号量称为二元信号量,而可以取多个正整数的信号量被称为通用信号量。这里主要讨论二进制信号量。

信号量有关函数

  • int semget(key_t key, int nsems, int semflg);//用来创建或者访问一个信号量集,第二个参数为信号量集合中共有多少个信号量,若成功,返回值表示信号量集的描述符

    • int semctl(int semid, int semnum, int cmd, …);//1.用来初始化semctl(semid,semnum, cmd, arg);//第一个参数为信号量集描述符,第二个参数为信号量集的第num个元素,第三个参数设置为SETVAL,最后一个参数为arg联合体。//2.用来销毁一个信号量
      semctl(semid, semnum, IPC_RMID);//
 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 semop(int semid, struct sembuf *sops, unsigned nsops);//用来信号量的PV操作,第二个参数为struct sembuf 结构体,系统会自己定义,第三个参数表示信号量集元素的个数
struct sembuf
  {
      short sem_num;   //信号量在数组的下标
      short sem_op;    //"-1"表示P,“1”表示V
      short sem_flg;   //默认为0                                                                                                                                                                                    
}

命令查看删除信号量集

  • 查看 ipcs -s

  • 删除 ipcrm -s semid

实现信号量保护临界资源

  • mysem.c

这里写图片描述
这里写图片描述

  • comm.c comm.h
    这里写图片描述
  • Makefile
    这里写图片描述

信号量的工作原理:

  • 信号量也属于进程间通信的方式之一,他的作用主要是保护临界资源因多个进程共同访问而造成的一系列问题,在上面的代码中,用fork创建出子进程,两个进程共同向显示屏打印字符,而在这里,两个进程的公共资源就是显示屏,因为cpu在对两个进程的调度是随机的,如果不对公共资源进行保护,打印出的结果就是字符A,B穿插,不是成对出现,如下图
    这里写图片描述
    如果要让信号量可以保护临界资源,使其在任何一个时间内,都有且仅有一个进程访问,首先,ftok用某种办法,得到一个相同的键值,再用相同的键值访问或者创建一个相同的信号量集,这样两个进程就可以共享信号量,我们在代码中将信号量的值设置为1,以子进程为列,想要访问临界资源的话,首先要进行P操作申请资源,如果这时候信号量的值小于等于0,它就必须要挂起等待资源,如果这时信号量值为1,它执行P操作申请资源,信号量值-1,这时,信号量值为0,如果父进程想要访问临界资源,也必须要挂起等待,在子进程完成对临界资源的访问后,它要执行v操作归还资源,这时,信号量+1,变为1,父进程就可以访问临界资源了。这样做后,打印出的结果如下图:
    这里写图片描述
    这种机制就实现了保护临界资源,使其在任何时间点,有且仅有一个进程访问。

五:SEM_UNDO

  • 当操作信号量(semop)时,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。
    如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值