1. 进程 A 排他锁住某文件之后,进程 B 可以修改该文件,但不能锁住该文件。
2. 进程 A 排他锁住某文件之后,进程 B 修改该文件之后,因为文件 inode 没有改变,所以依然不能锁住该文件。
3. 进程 A 排他锁住某文件之后,进程 B 可以删除该文件,并创建同名文件,此时进程 B 可以锁住该文件。
由于 vi, sed 等程序修改文件会改变文件 inode, 所以会导致被 A 进程锁住的文件,再用 vi, sed 等修改后依然能被进程 B 锁住。
下面的例子模拟了上述情景:
locking——一直锁住文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include <stdio.h>
#define FILE_CONTENTS "123"
int main()
{
int fd;
if (0 == access("lock.txt", F_OK))
{
printf("remove lock.txt!\n");
if (-1 == remove("lock.txt"))
{
printf("remove() failed.\n");
return -1;
}
}
fd = open("lock.txt", O_RDWR | O_CREAT | O_TRUNC | O_APPEND, S_IRUSR | S_IWUSR);
if (-1 == fd)
{
printf("open() failed.\n");
return -1;
}
if (-1 == write(fd, FILE_CONTENTS, sizeof(FILE_CONTENTS)))
{
printf("write() failed.\n");
return -1;
}
if (-1 == flock(fd, LOCK_EX))
{
printf("flock() failed.\n");
return -1;
}
sleep(60);
if (-1 == close(fd))
{
printf("close() failed.\n");
return -1;
}
return 0;
}
try_lock——尝试锁住文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include <stdio.h>
int main()
{
int fd;
printf("try_lock============================\n");
fd = open("lock.txt", O_RDONLY);
if (-1 == fd)
{
printf("open() failed.\n");
return -1;
}
printf("try lock!\n");
if (-1 == flock(fd, LOCK_EX | LOCK_NB))
{
printf("flock() failed.\n");
return -1;
}
if (-1 == close(fd))
{
printf("close() failed.\n");
return -1;
}
return 0;
}
append——追加修改锁住的文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define FILE_APPENDED_CONTENTS "123"
int main()
{
int fd;
printf("append============================\n");
fd = open("lock.txt", O_RDWR | O_APPEND);
if (-1 == fd)
{
printf("open() failed.\n");
return -1;
}
printf("append something to lock.txt!\n");
if (-1 == write(fd, FILE_APPENDED_CONTENTS, sizeof(FILE_APPENDED_CONTENTS)))
{
printf("write() failed.\n");
return -1;
}
if (-1 == close(fd))
{
printf("close() failed.\n");
return -1;
}
return 0;
}
rm_create——先删除锁住的文件,再创建相同文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define FILE_CONTENTS "123"
int main()
{
int fd;
printf("rm_create============================\n");
printf("remove lock.txt!\n");
if (-1 == remove("lock.txt"))
{
printf("remove() failed.\n");
return -1;
}
printf("create lock.txt!\n");
fd = open("lock.txt", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
if (-1 == fd)
{
printf("open() failed.\n");
return -1;
}
if (-1 == write(fd, FILE_CONTENTS, sizeof(FILE_CONTENTS)))
{
printf("write() failed.\n");
return -1;
}
if (-1 == close(fd))
{
printf("close() failed.\n");
return -1;
}
return 0;
}
运行顺序
1. 先单独运行 locking
2. 按如下顺序运行其他程序
#!/bin/sh
./try_lock
echo "################# before append"
ls -i lock.txt
./append
echo "################# after append"
ls -i lock.txt
./try_lock
echo "################# before rm_create"
ls -i lock.txt
./rm_create
echo "################# after rm_create"
ls -i lock.txt
./try_lock
输出如下:
> ./run.sh
try_lock============================
try lock!
flock() failed.
################# before append
2172298 lock.txt
append============================
append something to lock.txt!
################# after append
2172298 lock.txt
try_lock============================
try lock!
flock() failed.
################# before rm_create
2172298 lock.txt
rm_create============================
remove lock.txt!
create lock.txt!
################# after rm_create
2172299 lock.txt
try_lock============================
try lock!
修改文件之后,inode 没有变化,flock 失败;删除再创建相同文件,inode 改变,flock 成功。