IPC_信号量笔记



信号量:用于管理对资源的访问。
共享内存:用于在程序之间高效的共享数据。
消息队列:在程序之间传递数据的一种简单方法。


信号量:(被挂起而非忙等待)
1.临界代码:确保只有一个进程或一个线程有唯一访问权。(临界区域)
2.原因或者目的:为了防止出现多个程序同时访问一个共享资源而引发的问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。
3.线程可以使用互斥量和信号量(多线程的特例信号量)来对临界区的控制。本章信号量讲解主要针对进程间对临界区的控制。
4.信号量是一种特殊的变量,它只取正整数值,只允许对它进行等待和发送信号这两种操作,并且程序对其访问都是原子性操作。
P操作 用于等待 V操作:发送信号     passer  vrijgeven 这两个是荷兰语的等待(获取信号量的掌控权,不让你过:相对而言啦)和释放(释放掉对该信号量的掌控权,让你过去)的意思。
p:(如果有人过去了就)拦住你过去拿不到令牌进入      V:放你过去(把已经使用了的令牌给腾出来)
5.简单的信号量只能取值0和1的变量,即二进制信号量。可以取多个正整数的信号量被称为通用信号量。
6.p(n): 如果N大于0,就减去1;如果它==0,就挂起该进程的执行。(注意,只用一个普通的变量进程类似的加减法是不行的。)
  v(n): 如果其他进程因等待sv而被挂起,就让他回复运行;如果没有进程因等待n而被挂起,就给他加1.
7.信号量是两个以上进程都可以访问他。


以上是信号量的机制原理,以下是linux实现信号量的机制:
1.linux的信号量函数都是针对多个(成组)的通用信号量进程操作,而不是只针对一个二进制信号量:这对一个进程需要锁定多个资源的复杂情况中,这种对一组信号量进程操作的能力是一个巨大的优势。绝大多数使用它就足够满足我们的需求了。
#include <sys/sem.h>
int semctl(int sem_id, int sem_num, int command, ...);
int semget(key_t key, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
这些函数都是用来对成组的信号量进行操作的。这使得,对他们的操作要比单个信号量所需要的操作复杂得多。


一。semget()创建或获取一个信号量。key使得不相关的进程通过它访问同一个信号量。(程序对所有信号量的访问都是间接的,因为是由系统帮我们管的,只有系统管,各个进程才能够到系统那里去要,否则就无法达到进程间通信了)
key非0整数,sem_num信号量数目,取值通常为1的,sem_flags:IPC_CREATE IPC_EXCL可以确保一个新的、唯一的信号量,如果已经存在则返回一个错误。
二。semop()用于改变信号量的值。
sembuf *sem_ops是一个数组指针哦,别以为仅仅是一个struct的地址哦,虽然他可以表达这两个意思,但是你呢,要知道:这里指的是一个数组首地址,而非一个struct地址。
struct sembuf{ short sem_num /*表示数字的下标,从0开始,通常为0*/; short sem_op/*操作:-1表示p,+1表示v操作*/; short sem_flg/*一般设置为SEM_UNDO,表示让系统跟踪该信号量修改情况,如果进程是非正常终止的,没有释放该信号量,则系统会自动释放它,除非你想对他有自己的特殊操作,那就设置非SEM_UNDO值,那么你得自己管理好该信号量了哦*/;}
*semop()的动作是一次性的,原子性的,so:你别担心该函数同时被调的情况。具体的semop实现细节可以man
num_sem_ops:信号操作结构的数量,恒大于或等于1。
三。semctl()控制信号量信息。
sem_id:表示该信号组的id哟。
sem_num:表示对该组的某个元素(信号量)进行操作,一般取值为0.
command:操作参数:其中最常用的有SETVAL(初始化设置为已知的值),IPC_RMID(删除),这两种操作,成功时候返回0失败时返回-1,其他操作command就不一定了。
如果有第四个参数,那就是一个union semun结构


============================================
P: -1,取令牌,就少一个令牌咯;令牌不够就等待咯,够就继续往下咯。
V: +1,还令牌,就多一个令牌咯;令牌交给下一个要令牌的人咯。
信号量是一种有限资源,希望大家节约使用;
消息队列也是一样滴。


注意:如果进程正常终止且没有释放信号量资源,那么该信号量会一直存在,如果下次继续使用,那么该信号量的值就是上次保存下来的值了,引起“乱”


*如果需要用到第4个参数,那么我们程序本身是需要自己定义union semun的。
semctl()  performs  the  control operation specified by cmd on the semaphore set identified by semid, or on the
       semnum-th semaphore of that set.  (The semaphores in a set are numbered starting at 0.)


       This function has three or four arguments, depending on cmd.  When there are four,  the  fourth  has  the  type
       union semun.  The calling program must define this union as follows:


           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) */
           };


       The semid_ds data structure is defined in <sys/sem.h> as follows:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值