临界资源与临界区
临界资源(critical resource):一次只能供一个进程使用的资源。 如:硬件有打印机等,软件有变量,磁盘文件(写入的时候)。
临界区(critical section):把进程中访问临界资源的那段代码成为临界区。
为了实现临界资源的互斥访问,只要做到进程互斥地进去自己的临界区,便可以实现进程对临界资源的互斥访问。
同步机制
为实现各进程互质地访问自己的临界区,操作系统需要同步机制来协调各进程的运行。
1、同步机制的规则
(1)空闲让进:当无进程处于临界区,表明临界资源处于空闲状态,允许请求进去临界区的进程进去临界区
(2)忙则等待:当有进程处于临界区,表明临界资源正在访问,其他请求进入临界区的进程必须等待。
(3)有限等待:应使在等待的进程在有限的事件内进入自己的临界区,避免"死等"状态
(4)让权等待:当进程不能进入自己的临界区,应立即释放处理机,以避免进入"忙等"状态
2、硬件同步机制
为临界资源设置一把锁,当临界资源无进程使用时,锁是打开的,当临界资源正在被进程使用时,则锁是关闭的。
锁可能是一个布尔变量lock,初始时,lock = FALSE,那么每次访问临界资源时,都要进程锁测试。
bool lock = false; if(!lock) { lock = true; access critical section;//访问临界区资源 }
但是在多任务的处理机中,可能会发生错误。假设有2个进程都要访问同一临界资源,进程a通过了锁测试,但是未将lock设为true时,发生了进程调度,进程b开始执行锁测试,同样通过了锁测试,从而使得两个进程访问同一个临界资源。
(1)关中断:在进入锁测试之前关闭中断,直到完成锁测试并且上锁之后才打开中断。
(2)利用Test-and-set指令:这是一条硬件指令,且该指令是原子操作(atomic operataion),原子操作指的是该执行过程要么不做,那么全做,即像原子一样不可分割。下面的TS就是一个原子操作,所以不会发生上面所说的问题。
bool TS(bool *lock)//lock 为临界资源的锁 { bool old ; old = lock; lock = true;//如果锁为true,那么这句不影响锁,如果锁为false,那么正好上锁 return old; }
while(TS(&lock));//循环测试直到TS(&lock) 为false access critical section; lock = false;
(3)利用Swap指令:该指令也是硬件指令,且是原子操作。可以看出下面的代码其实思想是和上面的代码思想是一样的。只不过实现方式不同而已。
void swap(bool *a, bool *b) { //如果a==true,那么swap语句不影响锁,如果a==false,那么正好上锁 bool tmp tmp = *a; *a = *b; *b = tmp; }
bool key = true; do{ swap(&lock,&key); }while(key!=false)