1fcntl记录锁
多个进程在一个给定的字节上可以有一把共享的读锁,但是在一个给定字节上的写锁则只能由一个进程独用。更进一步而言,如果在一个给定字节上已经有一把或多把读锁,则不能在该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁,则不能再对它加任何读锁。
用FG E T L K测试能否建立一把锁,然后用FS E T L K和FS E T L KW企图建立一把锁,这两者不是一个原子操作。在这两个操作之间可能会有另一个进程插入并建立一把相关的锁,使原来测试到的情况发生变化,如果不希望在建立锁时可能产生的长期阻塞,则应使用FS E T L K,并对返回结果进行测试,以判别是否成功地建立了所要求的锁。
在设置或释放文件上的一把锁时,系统按需组合或裂开相邻区。例如,若对字节0~ 9 9设置一把读锁,然后对字节0~ 4 9设置一把写锁,则有两个加锁区:0 ~ 4 9字节(写锁)及50 ~ 9 9(读锁)。又如,若10 0 ~ 1 9 9字节是加锁的区,需解锁第15 0字节,则内核将维持两把锁,一把用于10 0 ~ 1 4 9字节,另一把用于15 1 ~ 1 9 9字节。
2 死锁
如果两个进程相互等待对方持有并且不释放(锁定)的资源时,则这两个进程就处于死锁状态。如果一个进程已经控制了文件中的一个加锁区域,然后它又试图对另一个进程控制的区域加锁,则它就会睡眠,在这种情况下,有发生死锁的可能性。检测到死锁时,内核必须选择一个进程收到出错返回。
3 锁的隐含继承和释放
关于记录锁的自动继承和释放有三条规则:
(1)锁与进程、文件两方面有关。这有两重含意:第一重很明显,当一个进程终止时,它所建立的锁全部释放;第二重意思就不很明显,任何时候关闭一个描述符时,则该进程通过这一描述符可以存访的文件上的任何一把锁都被释放(这些锁都是该进程设置的)。这就意味着如果执行下列四步:
fd1=open(pathname,...);
read_lock(fd1,...);
f d 2 = d u p (f d 1 ) ;
c l o s e ( f d2 ) ;
则在cl o s e(fd 2)后,在fd 1上设置的锁被释放。如果将du p代换为op e n,其效果也一样:
fd1=open(pathname,...);
read_lock(fd1,...);
fd2=open(pathname,...);
c l o s e ( f d2 ) ;
(2) 由fo r k产生的子程序不继承父进程所设置的锁。这意味着,若一个进程得到一把锁,然后调用fo r k,那么对于父进程获得的锁而言,子进程被视为另一个进程,对于从父进程处继承过来的任一描述符,子进程要调用fc n tl以获得它自己的锁。这与锁的作用是相一致的。锁的作用是阻止多个进程同时写同一个文件(或同一文件区域)。如果子进程继承父进程的锁,则父、子进程就可以同时写同一个文件。
(3) 在执行ex e c后,新程序可以继承原执行程序的锁。