> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/sys/flock.2.md).

# flock(2)

`flock` — 对打开的文件应用或移除咨询锁

## 名称

`flock`

## 库

Lb libc

## 概要

`#include <sys/file.h>`

```c
#define LOCK_SH 0x01 /* 共享文件锁 */
#define LOCK_EX 0x02 /* 独占文件锁 */
#define LOCK_NB 0x04 /* 加锁时不阻塞 */
#define LOCK_UN 0x08 /* 解锁文件 */

int
flock(int fd, int operation)
```

## 描述

`flock()` 系统调用对与文件描述符 `fd` 关联的文件应用或移除*咨询*锁。通过指定 `operation` 参数为 `LOCK_SH` 或 `LOCK_EX` 之一，并可选地加上 `LOCK_NB` 来应用锁。要解锁现有的锁，`operation` 应为 `LOCK_UN`。

咨询锁允许协作进程对文件执行一致的操作，但不保证一致性（即进程仍可能在不使用咨询锁的情况下访问文件，可能导致不一致）。

此加锁机制允许两种类型的锁：*共享*锁和*独占*锁。在任何时候，可以对一个文件应用多个共享锁，但绝不允许同时存在多个独占锁，或同时存在共享锁和独占锁。

共享锁可以*升级*为独占锁，反之亦然，只需指定适当的锁类型；这会导致释放先前的锁并应用新锁（可能在此期间其他进程已获取并释放了该锁）。

请求对已加锁对象的锁通常会导致调用者阻塞，直到可以获取锁。如果 `operation` 中包含 `LOCK_NB`，则不会发生这种情况；相反，调用将失败并返回 `EWOULDBLOCK` 错误。

## 注释

锁针对的是文件，而非文件描述符。也就是说，通过 [dup(2)](/sys/dup.2.md) 或 [fork(2)](/sys/fork.2.md) 复制的文件描述符不会产生锁的多个实例，而是对单个锁的多个引用。如果持有文件锁的进程执行 `fork()`，且子进程显式解锁该文件，父进程将失去其锁。

`flock()`、[fcntl(2)](/sys/fcntl.2.md) 和 [lockf(3)](/sys-1/lockf.3.md) 锁是兼容的。使用不同加锁接口的进程可以在同一文件上安全地协作。但是，在同一进程内只应使用其中一种接口。如果进程通过 `flock()` 对文件加锁，从使用 [fcntl(2)](/sys/fcntl.2.md) 或 [lockf(3)](/sys-1/lockf.3.md) 的另一个进程的角度看，该文件内的任何记录都将被视为已加锁，反之亦然。

阻塞等待锁的进程可被信号唤醒。

## 返回值

成功完成时，`flock()` 函数返回值 0；否则返回值 -1，并设置全局变量 `errno` 以指示错误。

## 错误

`flock()` 系统调用在以下情况下失败：

**\[`EWOULDBLOCK`]** 文件已加锁，且指定了 `LOCK_NB` 选项。

**\[`EBADF`]** `fd` 参数是无效的描述符。

**\[`EINVAL`]** `fd` 参数引用的不是文件对象。

**\[`EOPNOTSUPP`]** `fd` 参数引用的对象不支持文件加锁。

**\[`ENOLCK`]** 请求了锁，但没有可用的锁。

## 参见

[close(2)](/sys/close.2.md), [dup(2)](/sys/dup.2.md), [execve(2)](/sys/execve.2.md), [fcntl(2)](/sys/fcntl.2.md), [fork(2)](/sys/fork.2.md), [open(2)](/sys/open.2.md), flopen(3), [lockf(3)](/sys-1/lockf.3.md)

## 历史

`flock()` 系统调用出现于 4.2BSD。
