> 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-1/lockf.3.md).

# lockf(3)

`lockf` — 文件记录锁定

## 名称

`lockf`

## 库

libc

## 概要

```c
#include <unistd.h>

int
lockf(int fd, int function, off_t size);
```

## 描述

`lockf` 函数允许以咨询模式锁定文件的各个部分。其他进程尝试锁定已锁定部分的 `lockf` 调用将返回错误值或阻塞，直到该部分被解锁。进程终止时，该进程的所有锁都被移除。

参数 `fd` 是一个打开的文件描述符。该文件描述符必须以只写（`O_WRONLY`）或读写（`O_RDWR`）方式打开。

`function` 参数是一个控制值，指定要采取的操作。`function` 的允许值如下：

| **功能**    | **描述**          |
| --------- | --------------- |
| `F_ULOCK` | 解锁已锁定的部分        |
| `F_LOCK`  | 独占锁定一个部分        |
| `F_TLOCK` | 测试并独占锁定一个部分     |
| `F_TEST`  | 测试一个部分是否被其他进程锁定 |

`F_ULOCK` 移除文件某一部分的锁；`F_LOCK` 和 `F_TLOCK` 在该部分可用时锁定文件的一个部分；`F_TEST` 检测指定部分上是否存在其他进程的锁。

`size` 参数是要锁定或解锁的连续字节数。要锁定或解锁的部分从文件中的当前偏移量开始，对于正值向前延伸，对于负值向后延伸（即当前偏移量之前直到但不包括当前偏移量的字节）。但是，不允许锁定在文件开头之前开始或延伸的部分。如果 `size` 为 0，则从当前偏移量到最大可能文件偏移量的部分被锁定（即从当前偏移量到当前或任何未来的文件末尾）。

用 `F_LOCK` 或 `F_TLOCK` 锁定的部分可以全部或部分包含同一进程之前锁定的部分，或被其包含。当这种情况发生时，或当会产生相邻的已锁定部分时，这些部分被合并为一个单独的已锁定部分。如果请求将导致锁的数量超过系统规定的限制，则请求将失败。

`F_LOCK` 和 `F_TLOCK` 请求的区别仅在于该部分不可用时采取的操作不同。`F_LOCK` 阻塞调用进程，直到该部分可用。`F_TLOCK` 在该部分已被其他进程锁定时使函数失败。

文件锁在锁定进程首次关闭该文件的任何文件描述符时被释放。

`F_ULOCK` 请求释放（全部或部分）由该进程控制的一个或多个已锁定部分。已锁定部分将从当前文件偏移量开始解锁 `size` 个字节，如果 size 为 0 则解锁到文件末尾。当一个已锁定部分未完全释放时（即要解锁区域的起始或末尾落在某个已锁定部分内），该部分的剩余部分仍被该进程锁定。释放已锁定部分的中间部分将导致剩余的已锁定起始和末尾部分成为两个独立的已锁定部分。如果请求将导致系统中的锁数量超过系统规定的限制，则请求将失败。

如果 `F_ULOCK` 请求中 size 非零且所请求部分最后一个字节的偏移量是 off\_t 类型对象的最大值，而该进程已有一个 size 为 0 且包含所请求部分最后一个字节的锁，则该请求将被视为从所请求部分的起始处以等于 0 的 size 进行解锁的请求。否则，`F_ULOCK` 请求将仅尝试解锁所请求的部分。

如果控制某个已锁定区域的进程因尝试锁定另一个进程的已锁定区域而被置于休眠状态，则可能发生死锁。本实现检测到休眠等待已锁定区域解锁会导致死锁时，将以 `EDEADLK` 错误失败。

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

对某个部分的阻塞可被任何信号中断。

## 返回值

如果成功，`lockf` 函数返回零；否则返回一个错误号以指示错误。失败时，现有锁不会被改变。

## 错误

`lockf` 函数在以下情况下将失败：

**`[EAGAIN]`** 参数 `function` 为 `F_TLOCK` 或 `F_TEST`，且该部分已被其他进程锁定。

**`[EBADF]`** 参数 `fd` 不是有效的打开文件描述符。参数 `function` 为 `F_LOCK` 或 `F_TLOCK`，且 `fd` 不是有效的以写入方式打开的文件描述符。

**`[EDEADLK]`** 参数 `function` 为 `F_LOCK` 且检测到死锁。

**`[EINTR]`** 参数 `function` 为 `F_LOCK`，且 `lockf` 被信号传递中断。

**`[EINVAL]`** 参数 `function` 不是 `F_ULOCK`、`F_LOCK`、`F_TLOCK` 或 `F_TEST` 之一。参数 `fd` 引用不支持锁定的文件。

**`[ENOLCK]`** 参数 `function` 为 `F_ULOCK`、`F_LOCK` 或 `F_TLOCK`，且满足锁定或解锁请求将导致系统中已锁定区域数量超过系统规定的限制。

## 参见

fcntl(2), flock(2)

## 标准

`lockf` 函数遵循 -xpg4.2。
