对文件加锁是原子性的,可以用于进程间文件操作的同步。在linux下,有三个函数可以对文件进程加锁,分别是fcntl、flock、lockf。这里只说fcntl,它的用法也是最复杂的。 fcntl是file control的缩写。在linux下大部分设备都是文件,所以fcntl的功能也比较多,包括: •Duplicating a file descriptor(复制文件描述符) •File descriptor flags(操作close-on-exec标志) •File status flags(操作文件O_RDONLY , O_WRONLY , O_RDWR , O_APPEND , O_NONBLOCK , O_SYNC和O_ASYNC标识) •Advisory locking(建议性锁) •Mandatory locking(强制性锁) •Managing signals(管理信号) •Leases(租借锁) •File and directory change notification (dnotify)(文件和目录更改消息) •Changing the capacity of a pipe(改变管道大小) 这里只说一下Advisory locking和Mandatory locking。建议性锁是指给文件上锁后,只在文件上设置了一个锁的标识。其他进程在对这个文件进程操作时,可以检测到锁的存在,但这个锁并不能阻止它对这个文件进行操作。这就好比红绿灯,当亮红灯时,告诉你不要过马路,但如果你一定要过,也拦不住你。强制性锁则是当给文件上锁后,当其他进程要对这个文件进程不兼容的操作(如上了读锁,另一个进程要写),则系统内核将阻塞后来的进程直到第一个进程将锁解开。在该功能下,fcntl的函数原型为:
复制代码代码如下: #include <unistd.h> #include <fcntl.h></p><p>int fcntl(int fd, int cmd,struct flock *plock );</p><p>struct flock { ... short l_type;/* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence;/* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* Starting offset for lock */ off_t l_len; /* Number of bytes to lock */ pid_t l_pid; /* PID of process blocking our lock (F_GETLK only) */ ... };
在上面的代码中,"_lock.l_type = F_RDLCK;"表示给文件上读共享锁,"_lock.l_whence = SEEK_SET;"表示从文件开头开始加锁,"_lock.l_start = 0;"表示偏移l_whence多少字节开始加锁,"_lock.l_len = 0;"表示加锁的字节数,即长度(Specifying 0 for l_len has the special meaning: lock all bytes starting at the location specified by l_whence and l_start through to the end of file, no matter how large the file grows.)。 在上面的代码中,分别编译为slock、glock。先运行slock再运行glock:
复制代码代码如下: ./slock sleep now ... ./glock lock is 1 exit...
复制代码代码如下: Tomake use of mandatory locks, mandatory locking must be enabled both on the filesystem that contains the file to be locked, and on thefile itself. Mandatorylockingisenabled on a filesystem using the "-o mand" option to mount(8), or the MS_MANDLOCK flag for mount(2). Mandatory locking is enabled on a file by disabling group execute permission on the file and enabling the set-group-ID permission bit (seechmod(1) and chmod(2)).