关于flock
昨天在研究dropbear实现时,看到初始化脚本/etc/init.d/dropbear中有关于文件锁lock的内容,如下:
lock /tmp/.switch2jffs
mkdir -p /etc/dropbear
mv /tmp/dropbear/dropbear_* /etc/dropbear/
lock -u /tmp/.switch2jffs
以为lock是linux命令,百度一下,发现没有这个命令,查找lock来源:
root@hbg:/# which lock
/bin/lock
root@hbg:/# ls -al /bin/lock
lrwxrwxrwx 1 root root 7 Jan 17 14:20 /bin/lock -> busybox
root@hbg:/#
在busybox中查看到了源码:
代码很简单,lock有三个参数可选:
root@hbg:/# lock -h
Usage: lock [-suw] <filename>
-s Use shared locking 使用共享锁
-u Unlock 解锁
-w Wait for the lock to become free, don't acquire lock 阻塞等待解锁
主要代码如下:
static int do_lock(void)
{
int pid;
char pidstr[8];
// 打开文件
if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) {
if ((fd = open(file, O_RDWR)) < 0) {
fprintf(stderr, "Can't open %s\n", file);
return 1;
}
}
// 加锁(共享锁或互斥锁)
if (flock(fd, (shared ? LOCK_SH : LOCK_EX)) < 0) {
fprintf(stderr, "Can't lock %s\n", file);
return 1;
}
pid = fork();
if (pid < 0)
return -1;
// 子进程
if (pid == 0) {
signal(SIGKILL, exit_unlock);
signal(SIGTERM, exit_unlock);
signal(SIGINT, exit_unlock);
if (waitonly)
exit_unlock(0);
else
while (1)
sleep(1);
} else {
// 父进程
if (!waitonly) {
lseek(fd, 0, SEEK_SET);
ftruncate(fd, 0);
sprintf(pidstr, "%d\n", pid);
write(fd, pidstr, strlen(pidstr));
close(fd);
}
return 0;
}
return 0;
通过代码可以看到调用的是flock函数。
=====================================
简单了解一下flock函数:
#include <sys/file.h>
int flock(int fd, int operation);
参数operation有一下四种情况:
LOCK_SH:建立共享锁,多个进程可以对同一个文件作共享锁定。
LOCK_EX:建立互斥锁,一个文件同时只有一个互斥锁定。
LOCK_UN:解除文件锁定状态。
LOCK_NB:无法建立锁定时,此操作可被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX做OR(|)组合。
单一文件无法同时建立共享锁定或互斥锁定,当使用dup()或fork()时文件描述词不会继承此种锁定。
返回0表示成功,-1表示错误,错误代码存于errno中。
flock只能对整个文件加锁,不能对文件的一部分进行加锁。