
信号量的本质是一种数据操作锁、用来负责数据操作过程中的互斥、同步等功能。
信号量用来管理临界资源的。它本身只是一种外部资源的标识、不具有数据交换功能,而是通过控制其他的通信资源实现进程间通信。
可以这样理解,信号量就相当于是一个计数器。当有进程对它所管理的资源进行请求时,进程先要读取信号量的值,大于0,资源可以请求,等于0,资源不可以用,这时进程会进入睡眠状态直至资源可用。当一个进程不再使用资源时,信号量+1(对应的操作称为V操作),反之当有进程使用资源时,信号量-1(对应的操作为P操作)。对信号量的值操作均为原子操作。
1、什么是临界资源?什么是临界区???
临界资源:一次只允许一个进程使用的资源。
临界区:访问临界资源的程序代码片段。
2、为什么要使用信号量???
为了防止多个进程在访问共享资源为引发的问题。信号量可以协调进程对共享资源的访问,也就是用来保护临界资源的。任一时刻只能有一个执行线程进入临界区。
3.1、头文件
3.2、创建/获取一个信号量集合
返回值:成功返回信号量集合的semid。失败返回-1。
key:可以用 key_t ftok(const char* pathname,int proj_id) 获取。
nsems:这个参数表示你要创建的信号量集合中的信号量的个数。信号量只能以集合的形式创建。
semflg:同时使用IPC_CREAT和IPC_EXCL则会创建一个新的信号量集合。若已经存在的话则返回-1。单独使用IPC_CREAT的话会返回一个新的或者已经存在的信号量集合。
3.3、信号量结合的操作
返回值:成功返回0,失败返回-1。
sem_num: 为信号量是以集合的形式存在的,就相当所有信号量在一个数组里边,sem_num表示信号量在集合中的编号。
sem_op:表示该信号量的操作(P操作还是V操作)。如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权
sem_flg:信号操作标志,它的取值有两种。IPC_NOWAIT和SEM_UNDO。
IPC_NOWAIT:对信号量的操作不能满足时,semop()不会阻塞,而是立即返回,同时设定错误信息。
SEM_UNDO: 程序结束时(不管是正常还是不正常),保证信号值会被设定semop()调用之前的值。这样做的目的在于避免程序在异常的情况下结束未将锁定的资源解锁(死锁),造成资源永远锁定。
nsops:表示要操作信号量的个数。因为信号量是以集合的形式存在,所以第二个参数可以传一个数组,同时对一个集合中的多个信号量进行操作。
3.4、 int semctl(int semid,int semnum,int cmd,...);
semctl()在semid标识的信号量集合上,或者该信号量集合上第semnum个信号量上执行cmd指定的控制命令。根据cmd不同,这个函数有三个或四个参数,当有第四个参数时,第四个参数的类型是union。
3.5、命令:ipcs -s //查看创建的信号量集合的个数
ipcrm -s semid //删除一个信号量集合
IPC种的信号量一般指的是二元信号量,他就相当于互斥锁,当一个进程在等待资源时,该进程会被挂起,也就是修改这个进程PCB中的状态,让它从r跳到其他状态。然后把这个进程的PCB放到信号量集合的等待队列中。
栗子:
父进程中打印AA,子进程中打印BB。利用信号量使得AA和BB之间不出现混叠。因为打印的内容都要输入到显示器上,要不混叠的话,显示器就是临界资源。我们需要在父子进程的临界区进行加锁。
你想更深入了解学习Linux知识体系,你可以看一下我们花费了一个多月整理了上百小时的几百个知识点体系内容:
【超全整理】《Linux云计算从入门到精通》系列实战笔记全放送
