Note: 文中部分内容截取自 File locking in Linux
Prior knowledge
在了解文件锁之前先简单介绍一下File
相关的知识。
在C程序中Files由文件指针(file pointers
)或文件描述符(file descriptors
)来指定。ISO C的标准I/O库函数( stdio.h
中的fopen, fscanf, fprintf, fread, fwrite, fclose等等)用的是文件指针;UNIX 中的I/O函数(unistd.h
中的open, read, write, close和ioctl)使用的文件描述符。文件指针和文件描述符提供了用于执行独立于设备的输入输出逻辑标识(logical designations),成为句柄(handle
)。其中代表标准输入,标准输出和标准错误的文件指针的符号名(symbolic names)分别为stdin, stdout, stderr
。而代表标准输入,标准输出和标准错误的文件描述符的符号名(symbolic names)分别为STDIN_FILENO, STDOUT_FILENO, STDERR_FILENOE
。
head file | standard | file representation | 标准输入 | 标准输出 | 标准错误 |
---|---|---|---|---|---|
stdio.h | ISO I/O | file pointers | stdin | stdout | stderr |
unistd.h | UNIX I/O | file descriptors | STDIN_FILENO | STDOUT_FILENO | STDERR_FILENOE |
File descriptors
open函数将文件或物理设备与程序中使用的逻辑句柄(logical handle
)相关联。文件或物理设备通常由字符串来指定。句柄是一个整数,可以将其理解为指向进程特定的文件描述符表(file descriptor table
)的索引(index
)。进程中每个打开的文件,文件描述符表中都有其对应的条目(entry
)。文件描述符表是进程用户区(the process of user area
)的一部分。程序只能通过使用文件描述符的函数才能访问它。
例如我们调用open函数打开某文件时,会在文件描述符表中创建一个新的条目指向系统文件表(system file table)中的条目,
myfd = open("/home/my.data", O_RDONLY);
如图所示:
(ENV) [root@ceph-2 ~]# ll /proc/`pgrep prometheus`/fd
total 0
lr-x------ 1 root root 64 Apr 18 11:30 0 -> pipe:[29992]
l-wx------ 1 root root 64 Apr 18 11:30 1 -> pipe:[29993]
lr-x------ 1 root root 64 Apr 18 11:30 10 -> /prometheus/01E4TPBR3PZW9N9Y4WKA94CQMG/chunks/000002
lr-x------ 1 root root 64 Apr 18 11:30 11 -> /prometheus/01E4TPBR3PZW9N9Y4WKA94CQMG/index
lr-x------ 1 root root 64 Apr 18 11:30 12 -> /prometheus/01E5X7WKKNAWVWJP8F675CPJHR/chunks/000001
lr-x------ 1 root root 64 Apr 18 11:30 13 -> /prometheus/01E5X7WKKNAWVWJP8F675CPJHR/chunks/000002
lr-x------ 1 root root 64 Apr 18 11:30 14 -> /prometheus/01E5X7WKKNAWVWJP8F675CPJHR/chunks/000003
lr-x------ 1 root root 64 Apr 18 11:30 15 -> /prometheus/01E5X7WKKNAWVWJP8F675CPJHR/index
lr-x------ 1 root root 64 Apr 18 11:30 16 -> /prometheus/01E5BVP5DV4F05VMP1WC4KSKNN/index
lrwx------ 1 root root 64 Apr 18 11:30 17 -> socket:[182080336]
l-wx------ 1 root root 64 Apr 18 11:30 18 -> /prometheus/wal/00000120
lrwx------ 1 root root 64 Apr 18 11:30 19 -> socket:[182083422]
l-wx------ 1 root root 64 Apr 18 11:30 2 -> pipe:[29994]
lrwx------ 1 root root 64 Apr 18 11:30 20 -> socket:[182084022]
lrwx------ 1 root root 64 Apr 18 11:30 21 -> socket:[182083309]
lrwx------ 1 root root 64 Apr 18 11:30 7 -> socket:[29208]
lr-x------ 1 root root 64 Apr 18 11:30 70 -> /prometheus/01E6318BH2W76TQC1EXZZ9VZYF/chunks/000001
lr-x------ 1 root root 64 Apr 18 11:30 71 -> /prometheus/01E6318BH2W76TQC1EXZZ9VZYF/index
lr-x------ 1 root root 64 Apr 18 17:11 72 -> /prometheus/01E66886MNWDWNVX98CP360ZXM/chunks/000001
lr-x------ 1 root root 64 Apr 18 17:11 73 -> /prometheus/01E66886MNWDWNVX98CP360ZXM/index
lr-x------ 1 root root 64 Apr 18 11:30 76 -> /prometheus/01E65KN1255K3VN6YHSK6A436Q/chunks/000001
lr-x------ 1 root root 64 Apr 18 11:30 77 -> /prometheus/01E65KN1255K3VN6YHSK6A436Q/index
Introduction
File locking is a mutual-exclusion mechanism for files. Linux supports two major kinds of file locks:
- advisory locks
- mandatory locks
File descriptors and i-nodes
A file descriptor is an index in the per-process file descriptor table (in the left of the picture). Each file descriptor table entry contains a reference to a file object, stored in the file table (in the middle of the picture). Each file object contains a reference to an i-node, stored in the i-node table (in the right of the picture).
A file descriptor
is just a number that is used to refer a file object from the user space. A file object
represents an opened file. It contains things likes current read/write offset, non-blocking flag and another non-persistent state. An i-node
represents a filesystem object. It contains things like file meta-information (e.g. owner and permissions) and references to data blocks.
File descriptors created by several open()
calls for the same file path point to different file objects, but these file objects point to the same i-node. Duplicated file descriptors created by dup2()
or fork()
point to the same file object.
A BSD lock and an Open file description lock is associated with a file object, while a POSIX record lock is associated with an [i-node, pid]
pair. We’ll discuss it below.
(ENV) [root@ceph-2 ~]# lslocks
COMMAND PID TYPE SIZE MODE M START END PATH
atd 1007 POSIX 5B WRITE 0 0 0 /run/atd.pid
dockerd 996 FLOCK 32K WRITE 0 0 0 /var/lib/docker/volumes/metadata.db
ceph-mon 20226 POSIX 0B WRITE 0 0 0 /var/lib/ceph/mon/ceph-ceph-2/store.db/LOCK
etcd 1927 FLOCK 61M WRITE 0 0 0 /opt/sds/etcd/10.255.101.74.etcd/member/wal/000000000000001c-0000000000bf6bc6.w
java 3687 POSIX 0B WRITE 0 0 0 /usr/share/elasticsearch/data/nodes/0/indices/fsEGojTsQ_-mOId2lvPkzw/0/index/wr
(ENV) [root@ceph-2 ~]# cat /proc/locks
1: POSIX ADVISORY WRITE 3687 08:01:203193430 0 EOF
2: POSIX ADVISORY WRITE 3687 08:01:35313181 0 EOF
3: POSIX ADVISORY WRITE 3687 08:01:303759598 0 EOF
4: POSIX ADVISORY WRITE 3687 08:01:169440475 0 EOF
5: POSIX ADVISORY WRITE 3687 08:01:270424087 0 EOF
6: POSIX ADVISORY WRITE 3687 08:01:237033099 0 EOF
7: POSIX ADVISORY WRITE 3687 08:01:102692284 0 EOF
8: POSIX ADVISORY WRITE 3687 08:01:5305924 0 EOF
9: POSIX ADVISORY WRITE 3687 08:01:169745104 0 EOF
10: POSIX ADVISORY WRITE 3687 08:01:270228547 0 EOF
11: POSIX ADVISORY WRITE 3687 08:01:237033579 0 EOF
12: POSIX ADVISORY WRITE 3687 08:01:304187409 0 EOF
13: FLOCK ADVISORY WRITE 15965 00:12:97153870 0 EOF
14: FLOCK ADVISORY WRITE 996 08:01:135038043 0 EOF
15: POSIX ADVISORY WRITE 408 00:12:14985 0 EOF
References:
File locking in Linux
Unix系统编程
https://golang.org/pkg/syscall/#Flock
https://www.ibm.com/developerworks/cn/linux/l-cn-filelock/
https://www.kancloud.cn/kancloud/understanding-linux-processes/52169
https://linkscue.com/2018/09/07/2018-09-07-golang-flock-example/
golang的文件锁操作
有疑问加站长微信联系(非本文作者)