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 成功。