Linux 文件鎖與 inode

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






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章