一、临界资源
被多个进程能够看到的公共资源 叫做 临界资源。(管道和共享内存都叫临界资源,只是管道是安全的,共享内存是不安全的)
如果没有对临界资源进行任何保护,对于临界资源的访问,双方进程在进行访问的时候,就都是乱序的,可能会因为读写交叉而导致的各种乱码,废弃数据,等访问控制方面的问题。(例如父子进程的任意printf,因为显示器就是父子进程的临界资源)。
二、临界区
对多个进程而言,进程代码中,有大量的代码,只有一部分代码,会访问临界资源,这部分访问临界资源的代码,叫做,临界区。
原子性:我们把一件事情,要不没做,要么做完了——原子性——没有中间状态。
互斥:任何时刻,只允许一个进程,访问临界资源。
注意:共享内存没有进行同步与互斥。
三、信号量,信号灯
(一)信号量
信号量本质是一个计数器。定义:信号量是一个计数器,这个计数器对应的PV操作(V ++ P --)是原子的。
信号量的PV操作:V ++归还资源,P --申请资源。
你怎么证明放映厅里面特定的座位是你的呢?——我只要买到了票,这个座位就是我的。
看电影为类比,假设一个放映厅(临界资源)有100个座位(座位就是临界资源的一小块),100个座位对应100张票,用cnt计数:cnt=100,if(cnt <= 0) wait ;else return cnt–;卖一张票,cnt–,卖完了就等待。这个cnt就类似于信号量。
二元信号量:只能为0或为1的信号量称为二元信号量。为1的时候,表现的就是互斥特性。
——类比看电影,这时一个放映厅(临界资源)就一个座位,只能一个人(进程)进入,当一个人进入坐上这个座位看电影时,这个行为就是互斥访问。
常规信号量:多元信号量:
多个人看电影不是直接冲进放映厅抢座位,而是去抢票 -> 本质就是对 信号量(int cnt = 100) 进行抢占申请
任何人想看电影——必须先申请计数器cnt——如果申请成功,就一定能看到电影
任何进程想访问临界资源——必须现申请信号量——如果申请成功,就一定能访问临界资源中的一部分资源[信号量(1,0)互斥]
你怎么证明放映厅里面特定的座位是你的呢?——我只要买到了票,这个座位就是我的。
(二)信号量操作
sem: – :申请资源: P
sem:++:释放资源:V
信号量对应的操作是PV操作,PV操作是原子的。
共享内存不做访问控制,可以通过信号量进行对资源保护!
创建 释放 对应操作 查看 删除
shmget:创建共享内存 shmctl shmat,shmdt ipcs -m ipcrm -m
msgget:创建消息队列 msgctl msgsnd,msgrcv ipcs -q ipcrm -q
semget:创建信号量 semctl semop -> +1 -1 PV ipcs -s ipcrm -s
结构体的第一个元素的地址,在数字上和结构体整体的地址大小是一样的!
信号量主要用于实现同步操作,只要资源数大于0就表示可获取,可访问。若要使用信号量模拟实现互斥,则需要初始化资源计数为1,表示资源只有一个,则只有一个执行流能访问!