Linux flock和fcntl函数详解
文章目录
- flock函数
- 描述
- 返回值和错误码
- 笔记
- fcntl函数
- 描述
- 复制文件描述符
- 文件描述标志
- 文件状态标志
- 咨询锁
- 强制锁
- 管理信号
- 租赁
- 文件和目录变更通知
- 改变管道容量
- 返回值
- 错误
- 备注
- 遗留问题
flock函数
主要功能是在已打开的文件应用或者删除共享锁或者独占锁。sys/file.h声明了这个函数,声明的原型是:int flock(int fd, int operation)。

描述
-
fd是文件描述符。operation可以是下列参数之一:LOCK_SH:放置共享锁。多个进程可能在给定时间持有给定文件的共享锁。LOCK_EX:放置独占锁。在给定时间只有一个进程可以持有给定文件的排他锁。LOCK_UN:删除此进程持有的现有锁。
-
如果另一个进程持有不兼容的锁,则对
freeze()的调用可能会阻塞。要发出非阻塞请求,请在上述任何操作中包含LOCK_NB(通过 ORing)。 -
单个文件不能同时拥有共享锁和排它锁。
-
由
flock()创建的锁与打开的文件表条目相关联。这意味着重复的文件描述符(例如,由 fork 或 dup 创建的)引用相同的锁,并且可以使用这些描述符中的任何一个来修改或释放该锁。此外,锁可以通过对任何这些重复描述符执行显式 LOCK_UN 操作来释放,或者当所有此类描述符都已关闭时释放。 -
如果进程使用
open(或类似的)来获取同一文件的多个描述符,则这些描述符将由flock()独立处理。使用这些文件描述符之一锁定文件的尝试可能会被调用进程已经通过另一个描述符放置的锁拒绝。 -
进程只能在文件上持有一种类型的锁(共享或独占)。后续对已锁定文件的
flock()调用会将现有锁定转换为新的锁定模式。 -
由flock() 创建的锁在
execve中保留。 -
无论文件打开的模式如何,都可以对文件放置共享锁或独占锁。
返回值和错误码
- 成功后,返回零。出错时,返回 -1,并适当设置
errno。 EBADF:fd 不是打开的文件描述符。EINTR:在等待获取锁时,调用被处理程序捕获的信号的传递中断;参见信号signals相关文档。EINVAL:操作无效。ENOLCK:内核内存不足,无法分配锁定记录。EWOULDBLOCK:文件被锁定并选择了LOCK_NB标志。
笔记
flock()调用首次出现在BSD4.2中。在大多数 UNIX 系统上都出现了一个flock()版本,可能是根据fcntl()实现的。flock()不会锁定 NFS 上的文件。使用fcntl()代替。如果 Linux 版本足够新并且服务器支持锁定,它确实可以通过 NFS 工作。- 从内核 2.0 开始,
flock()本身被实现为系统调用,而不是在GNU C库中模拟为对fcntl()的调用。这产生了真正的BSD语义:flock()和fcntl()放置的锁类型之间没有交互,并且flock()不检测死锁。 flock()放置的锁不具有强约束力。实现了协议的软件才支持(比如SSH和PUTTY)。它给定文件的适当权限,进程可以自由地忽略flock()的使用并在文件上执行I/O。- 对于
fork()进程和dup(),flock()和fcntl()锁具有不同的语义。在使用fcntl()实现flock()的系统上,flock()的语义将与Linux手册中描述的语义不同。 - 转换锁(共享锁到独占锁,或反之亦然)不保证是原子(线程安全)的:首先删除现有锁,然后建立新锁。在这两个步骤之间,可能会授予另一个进程的挂起锁定请求,结果是转换要么阻塞,要么在指定
LOCK_NB的情况下失败。 这是原始的 BSD 行为,并且发生在许多其他实现中。
fcntl函数
操作文件描述符的函数。两个头文件须引入:
#include <unistd.h>
#include <fcntl.h>
函数的声明原型是int fcntl(int fd, int cmd, ... /* arg */ );

描述
fcntl() 对打开的文件描述符 fd 执行各种操作。fcntl() 可以采用可选的第三个参数。操作指令由cmd决定,操作内容因硬件的差异而不同。是否需要此参数由 cmd 决定。所需的参数类型在每个 cmd 名称后面的括号中指示(大多数情况下,所需的类型是 int,我们使用名称 arg 来标识参数),如果不需要参数,则指定 void。
复制文件描述符
F_DUPFD:找到大于或等于arg的最小编号的可用文件描述符,并将其作为fd的副本。这与dup2不同,后者完全使用指定的描述符。有关dup2()的差异请查看相关文档。成功后,将返回新的描述符。F_DUPFD_CLOEXEC:与F_DUPFD一样,还为重复描述符设置close-on-exec标志。指定此标志允许程序避免额外的fcntl()F_SETFD操作来设置FD_CLOEXEC标志。有关此标志为何有用的说明,请参阅open()中O_CLOEXEC的描述。
文件描述标志
以下命令操作与文件描述符关联的标志。目前,只定义了一个这样的标志:FD_CLOEXEC,close-on-exec 标志。如果 FD_CLOEXEC 位为 0,文件描述符将在 execve() 期间保持打开状态,否则将被关闭。
F_GETFD:读取文件描述符标志;arg被忽略。F_SETFD:将文件描述符标志设置为arg指定的值。
文件状态标志
每个打开的文件描述都有某些关联的状态标志,由 open() 初始化,并可能由 fcntl() 修改。重复的文件描述符(使用 dup()、fcntl(F_DUPFD)、fork() 等创建)引用相同的打开文件描述,因此共享相同的文件状态标志。文件状态标志及其语义在 open() 相关文档中有描述。
F_GETFL:获取文件访问模式和文件状态标志;arg被忽略。F_SETFL:将文件状态标志设置为arg指定的值。arg中的文件访问模式(O_RDONLY、O_WRONLY、O_RDWR)和文件创建标志(即O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)将被忽略。在 Linux 上,此命令只能更改O_APPEND、O_ASYNC、O_DIRECT、O_NOATIME和O_NONBLOCK标志。
咨询锁
主要用于flock()函数。F_GETLK、F_SETLK 和 F_SETLKW 用于获取、释放和测试记录锁(也称为文件段锁或文件区域锁)是否存在。第三个参数 lock 是一个指向结构的指针,该结构至少具有以下字段(按未指定的顺序)。
struct flock {...short l_type; /* Type of lock: F_RDLCK,F_WRLCK, F_UNLCK */short l_whence; /* How to interpret l_start:SEEK_SET, SEEK_CUR, SEEK_END */off_t l_start; /* Starting offset for lock */off_t l_len; /* Number of bytes to lock */pid_t l_pid; /* PID of process blocking our lock(F_GETLK only) */...
};
该结构的 l_whence、l_start 和 l_len 字段指定我们希望锁定的字节范围。文件末尾之后的字节可能会被锁定,但文件开头之前的字节不会被锁定。
l_start 是锁的起始偏移量,并相对于以下任一位置进行解释: 文件的开头(如果 l_whence 为 SEEK_SET);当前文件偏移量(如果 l_whence 为 SEEK_CUR);或文件末尾(如果 l_whence 为 SEEK_END)。在最后两种情况下,l_start 可以是负数,前提是偏移量不在文件开头之前。
l_len 指定要锁定的字节数。如果l_len为正数,则要锁定的范围涵盖字节l_start直到l_start+l_len-1(包括l_start+l_len-1)。为 l_len 指定 0 具有特殊含义:锁定从 l_whence 和 l_start 指定的位置开始到文件末尾的所有字节,无论文件增长多大。
POSIX.1-2001 允许(但不要求)实现支持负 l_len 值;如果 l_len 为负数,则 lock 描述的间隔涵盖字节 l_start+l_len 直至(包括 l_start-1)。 Linux 从内核版本 2.4.21 和 2.5.49 开始支持这一点。
l_type 字段可用于在文件上放置读 (F_RDLCK) 或写 (F_WRLCK) 锁。任意数量的进程都可以在一个文件区域上持有读锁(共享锁),但只有一个进程可以持有写锁(独占锁)。独占锁排除所有其他锁,包括共享锁和独占锁。单个进程只能在文件区域上持有一种类型的锁;如果将新锁应用于已锁定区域,则现有锁将转换为新锁类型。 (如果新锁指定的字节范围与现有锁的范围不完全一致,则此类转换可能涉及拆分、收缩或与现有锁合并。)
-
F_SETLK (struct flock *)对
lock的l_whence、l_start和l_len字段指定的字节获取锁(当l_type为F_RDLCK或F_WRLCK时)或释放锁(当l_type为F_UNLCK时)。如果冲突的锁被另一个进程持有,则此调用返回 -1 并将errno设置为EACCES或EAGAIN。 -
F_SETLKW (struct flock *)与
F_SETLK一样,但如果文件上持有冲突锁,则等待该锁被释放。如果在等待时捕获到信号,则调用将被中断并(在信号处理程序返回后)立即返回(返回值 -1 且errno设置为EINTR;请查阅signal())。 -
F_GETLK (struct flock *)在输入此调用时,
lock描述了我们想要在文件上放置的锁。如果可以放置锁,则fcntl()实际上不会放置它,而是在lock的l_type字段中返回F_UNLCK并保持结构的其他字段不变。如果一个或多个不兼容的锁会阻止放置此锁,则fcntl()将在lock的l_type、l_whence、l_start和l_len字段中返回有关这些锁之一的详细信息,并将l_pid设置为持有该锁的进程的PID。
为了放置读锁,fd 必须打开以供读取。为了放置写锁,fd 必须打开以进行写入。要放置两种类型的锁,请以读写方式打开文件。
除了通过显式 F_UNLCK 删除记录锁之外,当进程终止或关闭任何引用持有锁的文件的文件描述符时,记录锁也会自动释放。这很糟糕:这意味着当由于某种原因库函数决定打开、读取和关闭文件(例如 /etc/passwd 或 /etc/mtab)时,进程可能会失去对文件的锁定。
记录锁不会由通过 fork() 创建的子进程继承,而是在 execve() 中保留。由于 stdio 库执行缓冲,因此应避免在该包中的例程中使用记录锁定;使用 read() 和 write() 代替。
强制锁
本章不符合POSIX规范。上述记录锁可以是建议性的,也可以是强制的,并且默认情况下是建议性的。咨询锁不强制执行,仅在协作进程之间有用。对所有进程强制执行强制锁。如果进程尝试对具有不兼容强制锁的文件区域执行不兼容访问(例如,read() 或 write()),则结果取决于是否为其打开的文件描述启用了 O_NONBLOCK 标志。如果未启用 O_NONBLOCK 标志,则系统调用将被阻止,直到锁被移除或转换为与访问兼容的模式。如果启用了 O_NONBLOCK 标志,则系统调用将失败并出现错误 EAGAIN。
要使用强制锁定,必须在包含要锁定的文件的文件系统和文件本身上启用强制锁定。使用 mount() 的“-o mand”选项或 mount() 的 MS_MANDLOCK 标志在文件系统上启用强制锁定。通过禁用文件的组执行权限并启用 set-group-ID 权限位(请参阅 chmod() 和 chmod()),可以对文件启用强制锁定。Linux 的强制锁定实现是不可靠的。请参阅下文详细说明的错误。
管理信号
F_GETOWN、F_SETOWN、F_GETOWN_EX、F_SETOWN_EX、F_GETSIG 和 F_SETSIG 用于管理 I/O 可用性信号。
-
F_GETOWN (void)返回(作为函数结果)当前接收文件描述符 fd 上事件的
SIGIO和SIGURG信号的进程 ID 或进程组。进程 ID 以正值形式返回;进程组 ID 作为负值返回(但请参阅下面的错误)。arg被忽略。 -
F_SETOWN (int)
将文件描述符fd上的事件接收SIGIO和SIGURG信号的进程 ID 或进程组 ID 设置为arg中给定的 ID。进程ID指定为正值;进程组 ID 指定为负值。最常见的是,调用进程将自身指定为所有者(即arg指定为getpid())。
如果使用fcntl()的F_SETFL命令在文件描述符上设置O_ASYNC状态标志,则只要该文件描述符上可以进行输入或输出,就会发送SIGIO信号。F_SETSIG可用于获取SIGIO以外的信号传递。如果此权限检查失败,则该信号将被默默丢弃。
向F_SETOWN指定的所有者进程(组)发送信号会受到与Kill()中所述相同的权限检查,其中发送进程是使用F_SETOWN的进程(但请参阅下面的错误)。
如果文件描述符fd引用套接字,则F_SETOWN还会选择当带外数据到达该套接字时传送的 SIGURG 信号的接收者。(SIGURG在select()报告套接字有“异常情况”的任何情况下都会发送。)
以下情况在 2.6.x 内核直至(包括)内核 2.6.11 中均成立:
如果在使用支持线程组(例如 NPTL)的线程库运行的多线程进程中为F_SETSIG赋予非零值,则为F_SETOWN赋予正值具有不同的含义:而不是标识整个进程的进程 ID,它是标识进程内特定线程的线程 ID。因此,当使用F_SETSIG时,可能需要将gettid()的结果而不是getpid()传递给F_SETOWN以获得合理的结果。 (在当前的 Linux 线程实现中,主线程的线程 ID 与其进程 ID 相同。这意味着单线程程序在这种情况下同样可以使用gettid()或getpid()。)但是请注意,本段中的语句不适用于为套接字上的带外数据生成的SIGURG信号:此信号始终发送到进程或进程组,具体取决于为F_SETOWN指定的值。
上述行为在 Linux 2.6.12 中被意外删除,并且不会恢复。 从 Linux 2.6.32 开始,使用F_SETOWN_EX将SIGIO和SIGURG信号定位到特定线程。 -
F_GETOWN_EX (struct f_owner_ex *)(内核2.6.32版本开始提供)返回由先前的
F_SETOWN_EX操作定义的当前文件描述符所有者设置。信息在arg指向的结构中返回,其形式如下:struct f_owner_ex {int type;pid_t pid; };类型字段将具有值
F_OWNER_TID、F_OWNER_PID或F_OWNER_PGRP之一。 pid 字段是一个正整数,表示线程 ID、进程 ID 或进程组 ID。有关详细信息,请参阅F_SETOWN_EX。 -
F_SETOWN_EX (struct f_owner_ex *)(内核2.6.32版本开始提供)此操作执行与
F_SETOWN类似的任务。它允许调用者将 I/O 可用性信号定向到特定的线程、进程或进程组。调用者通过arg指定信号的目标,arg是指向f_owner_ex结构的指针。type字段具有以下值之一,它们定义如何解释 pid-
F_OWNER_TID将信号发送到 pid 中指定了线程 ID(调用
clone()或gettid()返回的值)的线程。 -
F_OWNER_PID向 pid 中指定 ID 的进程发送信号。
-
F_OWNER_PGRP向pid中指定ID的进程组发送信号。 (请注意,与 F_SETOWN 不同,此处将进程组 ID 指定为正值。)
-
-
F_GETSIG (void)返回(作为函数结果)当输入或输出成为可能时发送的信号。值为零表示发送了
SIGIO。任何其他值(包括SIGIO)都是发送的信号,在这种情况下,如果与SA_SIGINFO一起安装,则信号处理程序可以使用附加信息。 arg 被忽略。 -
F_SETSIG (int)
将输入或输出变为可能时发送的信号设置为 arg 中给定的值。值为零表示发送默认的SIGIO信号。任何其他值(包括SIGIO)都是要发送的信号,在这种情况下,如果与SA_SIGINFO一起安装,则信号处理程序可以使用附加信息。
通过使用具有非零值的F_SETSIG,并为信号处理程序设置SA_SIGINFO(请参阅sigaction()),有关 I/O 事件的额外信息将传递到siginfo_t结构中的处理程序。如果si_code字段指示源是SI_SIGIO,则si_fd字段给出与事件关联的文件描述符。否则,没有指示哪些文件描述符正在挂起,您应该使用常用的机制(select()、poll()、read()和O_NONBLOCK设置等)来确定哪些文件描述符可用于 I/O。
通过选择实时信号(值 >=SIGRTMIN),可以使用相同的信号编号对多个 I/O 事件进行排队。 (排队取决于可用内存)。如果为信号处理程序设置了SA_SIGINFO,则可获得额外信息,如上所述。
请注意,Linux 对可以排队到进程的实时信号数量施加了限制(请参阅getrlimit()和signal()),如果达到此限制,则内核将恢复传递SIGIO,并且这信号被传递到整个进程而不是特定的线程。
使用这些机制,程序可以实现完全异步 I/O,而无需在大多数情况下使用 select() 或 poll()。
O_ASYNC、F_GETOWN、F_SETOWN 的使用特定于 BSD 和 Linux。 F_GETOWN_EX、F_SETOWN_EX、F_GETSIG 和 F_SETSIG 是 Linux 特定的。 POSIX 有异步 I/O 和 aio_sigevent 结构来实现类似的事情;这些也可以作为 GNU C 库 (Glibc) 的一部分在 Linux 中使用。
租赁
F_SETLEASE 和 F_GETLEASE(Linux 2.4 及以上版本)分别用于在文件描述符 fd 引用的打开文件描述上建立新租约并检索当前租约。文件租约提供了一种机制,当进程(“租约破坏者”)尝试open()或truncate()文件时,持有租约的进程(“租约持有者”)会收到通知(通过发送信号)。该文件描述符引用的文件。
-
F_SETLEASE:根据整数arg中指定的以下值设置或删除文件租约:F_RDLCK:取出已读租约。这将导致调用进程在打开文件进行写入或被截断时收到通知。读租约只能放置在以只读方式打开的文件描述符上。F_WRLCK:拿出写租约。这将导致调用者在打开文件进行读取或写入或被截断时收到通知。仅当该文件没有其他打开的文件描述符时,才可以对该文件放置写租约。F_UNLCK:从文件中删除我们的租约。
租约与打开的文件描述相关联(请参阅open())。这意味着重复的文件描述符(例如,由fork()或dup()创建的)引用相同的租约,并且可以使用这些描述符中的任何一个来修改或释放该租约。此外,通过对任何这些重复描述符执行显式F_UNLCK操作,或者当所有此类描述符都已关闭时,可以释放租约。
租赁只能在常规文件上进行。非特权进程只能对 UID(所有者)与该进程的文件系统 UID 匹配的文件进行租约。具有CAP_LEASE功能的进程可以获取任意文件的租约。 -
F_GETLEASE (void):通过返回F_RDLCK、F_WRLCK或F_UNLCK来指示与文件描述符fd关联的租约类型,分别指示读租约、写租约或无租约。arg被忽略。
当进程(“租约破坏者”)执行与通过F_SETLEASE建立的租约冲突的open()或truncate()时,系统调用将被内核阻止,并且内核通过向租约持有者发送信号来通知租约持有者(默认为SIGIO)。租约持有者应通过执行任何所需的清理操作来响应此信号的接收,以准备文件被另一个进程访问(例如,刷新缓存的缓冲区),然后删除或降级其租约。通过执行F_SETLEASE命令并将 arg 指定为F_UNLCK来删除租约。如果租约持有者当前持有该文件的写租约,并且租约破坏者正在打开该文件进行读取,则租约持有者将租约降级为读租约就足够了。这是通过执行F_SETLEASE命令并将arg指定为F_RDLCK来完成的。
如果租约持有者未能在/proc/sys/fs/lease-break-time中指定的秒数内降级或删除租约,则内核将强制删除或降级租约持有者的租约。
一旦启动租约中断,F_GETLEASE将返回目标租约类型(F_RDLCK或F_UNLCK,具体取决于与租约中断器兼容的类型),直到租约持有者自愿降级或删除租约,或者内核在租约结束后强制执行此操作休息定时器到期。
一旦租约被自愿或强制删除或降级,并且假设租约破坏者尚未解除其系统调用的阻塞,内核将允许租约破坏者的系统调用继续进行。
如果租约中断器阻塞的open()或truncate()被信号处理程序中断,则系统调用将失败并出现错误EINTR,但其他步骤仍然会发生,如上所述。如果租约破坏者在open()或truncate()中被阻塞时被信号杀死,则其他步骤仍然会发生,如上所述。如果租约破坏者在调用open()时指定了O_NONBLOCK标志,则调用会立即失败并出现错误EWOULDBLOCK,但其他步骤仍然会按照上面的描述进行。
用于通知租约持有者的默认信号是SIGIO,但可以使用fcntl()的F_SETSIG命令更改此信号。如果执行F_SETSIG命令(即使指定SIGIO),并且使用SA_SIGINFO建立信号处理程序,则处理程序将接收 siginfo_t 结构作为其第二个参数,并且该参数的si_fd字段将保存租用文件的描述符已被另一个进程访问。 (如果调用者持有多个文件的租约,这非常有用)。
文件和目录变更通知
F_NOTIFY (int)(Linux 2.4 及以上)当 fd 引用的目录或其包含的任何文件发生更改时提供通知。要通知的事件在 arg 中指定,arg 是通过对以下零个或多个位进行或运算指定的位掩码:
DN_ACCESS:文件被访问(read、pread、readv)DN_MODIFY:文件被修改(write、pwrite、writev、truncate、ftruncate)。DN_CREATE:创建了一个文件(open,creat,mknod,mkdir,link,symlink,rename)。DN_DELETE:文件被取消链接(unlink,rename到另一个目录,rmdir)。DN_RENAME:该目录中的文件被重命名(重命名)DN_ATTRIB:文件的属性已更改(chown、chmod、utime[s])。
为了获得这些定义,必须在包含任何头文件之前定义 _GNU_SOURCE 功能测试宏。
一系列 F_NOTIFY 请求是累积的,arg 中的事件被添加到已监视的集合中。要禁用所有事件的通知,请进行 F_NOTIFY 调用并将 arg 指定为 0。
通知是通过信号的传递发生的。默认信号是 SIGIO,但可以使用 fcntl() 的 F_SETSIG 命令进行更改。在后一种情况下,信号处理程序接收 siginfo_t 结构作为其第二个参数(如果处理程序是使用 SA_SIGINFO 建立的),并且该结构的 si_fd 字段包含生成通知的文件描述符(在多个目录上建立通知时有用)。
特别是在使用 DN_MULTISHOT 时,应该使用实时信号进行通知,以便可以将多个通知排队。注意:新应用程序应使用 inotify 接口(自内核 2.6.13 起可用),它提供了一个更高级的接口来获取文件系统事件的通知。请参阅 inotify 相关资料。
改变管道容量
F_SETPIPE_SZ (int);从Linux 2.6.35版本开始提供。将fd引用的管道的容量更改为至少为arg字节。非特权进程可以将管道容量调整为系统页面大小和/proc/sys/fs/pipe-max-size中定义的限制之间的任何值(请参阅proc())。尝试将管道容量设置为低于页面大小时会自动四舍五入到页面大小。非特权进程尝试将管道容量设置为高于/proc/sys/fs/pipe-max-size中的限制会产生错误EPERM;特权进程 (CAP_SYS_RESOURCE) 可以覆盖该限制。当为管道分配缓冲区时,如果方便实现,内核可以使用大于arg的容量。F_GETPIPE_SZ操作返回实际使用的大小。尝试将管道容量设置为小于当前用于存储数据的缓冲区空间量会产生错误EBUSY。F_GETPIPE_SZ(void)从Linux 2.6.35版本开始提供。返回(作为函数结果)fd 引用的管道的容量。
返回值
对于成功的调用,返回值取决于操作:
F_DUPFD:新的描述符。F_GETFD:文件描述符标志的值。F_GETFL:文件状态标志的值。F_GETLEASE:文件描述符上持有的租约类型。F_GETOWN:描述符所有者的值。F_GETSIG:当可以进行读取或写入时发送的信号值,或者对于传统的SIGIO行为为零。F_GETPIPE_SZ:管道容量。- 所有其它命令:0表示没有错误。出错时,返回 -1,并适当设置
errno。
错误
EACCES或EAGAIN:操作被其他进程持有的锁禁止。EAGAIN:该操作被禁止,因为该文件已被另一个进程进行内存映射。EBADF:fd不是打开的文件描述符,或者命令是F_SETLK或F_SETLKW并且文件描述符打开模式与请求的锁定类型不匹配。EDEADLK:检测到指定的F_SETLKW命令会导致死锁。EFAULT:锁位于您可访问的地址空间之外。EINTR:对于F_SETLKW,命令被信号中断;参见signal相关资料。对于F_GETLK和F_SETLK,在检查或获取锁之前命令被信号中断。最有可能发生在锁定远程文件时(例如,通过 NFS 锁定),但有时也可能发生在本地。EINVAL:对于F_DUPFD,arg为负数或大于最大允许值。对于F_SETSIG,arg不是允许的信号号。EMFILE:对于F_DUPFD,进程已经打开了最大数量的文件描述符。ENOLCK:打开太多段锁、锁表已满或远程锁定协议失败(例如,通过 NFS 锁定)。EPERM:尝试清除设置了仅附加属性的文件上的O_APPEND标志。
备注
- SVr4、4.3BSD、POSIX.1-2001。 POSIX.1-2001 中仅指定了操作
F_DUPFD、F_GETFD、F_SETFD、F_GETFL、F_SETFL、F_GETLK、F_SETLK和F_SETLKW。 F_GETOWN和F_SETOWN在 POSIX.1-2001 中指定。 (要获取它们的定义,请使用 500 或更大的值定义BSD_SOURCE或_XOPEN_SOURCE,或者使用 200809L 或更大的值定义_POSIX_C_SOURCE。)F_DUPFD_CLOEXEC在 POSIX.1-2008 中指定。 (要获得此定义,请将_POSIX_C_SOURCE定义为 200809L 或更大的值,或者将_XOPEN_SOURCE定义为 700 或更大的值。)F_GETOWN_EX、F_SETOWN_EX、F_SETPIPE_SZ、F_GETPIPE_SZ、F_GETSIG、F_SETSIG、F_NOTIFY、F_GETLEASE和F_SETLEASE是 Linux 特定的。 (定义_GNU_SOURCE宏来获取这些定义。)- 最初的 Linux
fcntl()系统调用并不是为了处理大文件偏移量(在集群结构中)而设计的。因此,Linux 2.4 中添加了fcntl()系统调用。较新的系统调用采用不同的文件锁定结构,flock和相应的命令F_GETLK64、F_SETLK64和F_SETLKW64。然而,使用 glibc 的应用程序可以忽略这些细节,其fcntl()包装函数透明地使用可用的更新的系统调用。 dup2返回的错误与F_DUPFD返回的错误不同。- 从内核 2.0 开始,
flock()和fcntl()放置的锁类型之间没有交互。 - 一些系统在
structflock中具有更多字段,例如l_sysid。显然,如果持有锁的进程可能位于不同的机器上,那么单独的l_pid不会很有用。
遗留问题
- 某些体系结构(尤其是 i386)上的 Linux 系统调用约定的限制意味着,如果
F_GETOWN返回的(负)进程组 ID 落在 -1 到 -4095 的范围内,则返回值会被 glibc 错误地解释为系统调用出错;也就是说,fcntl()的返回值为-1,并且errno将包含(正)进程组 ID。 Linux 特有的F_GETOWN_EX操作避免了这个问题。从 glibc 2.11 版开始,glibc 通过使用F_GETOWN_EX实现F_GETOWN来使内核F_GETOWN问题不可见。 - 在 Linux 2.4 及更早版本中,当非特权进程使用
F_SETOWN将套接字文件描述符的所有者指定为调用者之外的进程(组)时,可能会出现错误。在这种情况下,fcntl()可以返回 -1,并将errno设置为EPERM,即使调用者有权向其发送信号的所有者进程(组)也是如此。尽管返回此错误,但文件描述符所有者已设置,并且信号将发送给所有者。 - 所有已知版本的 Linux 中强制锁定的实现都受到竞争条件的影响,这导致其不可靠:与锁定重叠的
write()调用可能会在获取强制锁定后修改数据;与锁重叠的read()调用可能会检测仅在获取写锁后对数据所做的更改。强制锁和mmap()之间也存在类似的竞争。因此,不建议依赖强制锁定。
| 作者: | 岬淢箫声 |
| 日期: | 2023年11月3日 |
| 版本: | 1.0 |
| 链接: | http://caowei.blog.csdn.net |
相关文章:
Linux flock和fcntl函数详解
文章目录 flock函数描述返回值和错误码笔记 fcntl函数描述复制文件描述符文件描述标志文件状态标志 咨询锁强制锁管理信号租赁文件和目录变更通知改变管道容量 返回值错误备注遗留问题 flock函数 主要功能是在已打开的文件应用或者删除共享锁或者独占锁。sys/file.h声明了这个…...
React 组件点击事件
点击事件 点击事件方式1、传统类方法(不推荐)2、传统类方法 16.3.0 - 自动绑定(不推荐)3、箭头函数3.1、类组件3.2、函数组件3.3、内联箭头函数 4、useState Hook 点击事件方式 1、传统类方法(不推荐) 当…...
Windows 下编译 TensorFlow 2.9.1 CC库
参考 Intel 的 tensorflow 编译指导,不过项目还是可以用 TF原本的,不是一定要选择Intel 的TF版本。 安装 MSVC 2019 安装 Intel OneDNN OneMKL 似乎也可以不安装 ( & ) https://www.intel.cn/content/www/cn/zh/developer/articles/tool/one…...
Databricks 入门之连接外部数据库
连接方式应该很多,现在记录本人目前学习到的一种方式。 一、读取外部数据库 1.notebook执行语言为sql时可以通过JDBC方式加载数据库数据。 以下代码将可以将sqlserver中的表加载到databricks视图中,当然也可创建表来接收外部数据。 %sqlCREATE TEMPOR…...
家庭互动新维度:TikTok的亲子体验
在数字时代,家庭互动的方式正在发生翻天覆地的改变。社交媒体平台TikTok崭露头角,不仅在年轻用户中广受欢迎,还为家庭带来了全新的互动维度。本文将深入探讨TikTok如何成为家庭互动的新元素,以及它如何改变亲子体验。 TikTok&…...
redis教程 一 redis中的常用命令
文章目录 redis常见命令Redis数据结构介绍redis通用命令String类型String的常见命令Key结构 Hash类型List类型Set类型SortedSet类型 redis常见命令 Redis数据结构介绍 Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样&…...
【第28例】IPD体系进阶 | 需求管理:需求实现过程
目录 简介 内容详解 CSDN学院相关推荐 作者简介 简介 继续 IPD 体系中的需求管理相关的专题。 先来看看整个需求管理涉及的过程内容: 需求管理流程主要包含五个阶段: 需求收集; 需求分析; 需求分发/分配;...
聊聊我对AI Agents技术的一些看法
小伙伴们!我来兑现承诺啦~ ps:接下来期待什么内容,欢迎在评论区留言! 今天,我们就来聊聊大模型 Agent。 最近这几个月,Agent 这一概念可谓火出天际,从 AutoGPT 一周 6 万 star 刷新…...
32 mysql in 的实现
前言 这里我们主要是来探讨一下 mysql 中 in 的使用, find_in_set 的使用 这两者 在我们实际应用中应该也是 非常常用的了 测试数据表如下 CREATE TABLE tz_test (id int(11) unsigned NOT NULL AUTO_INCREMENT,field1 varchar(16) DEFAULT NULL,field2 varchar(16) DEFAU…...
Qt QtCreator添加自定义注释
在写代码的时候我们为了规范化,一般会加文件注释、类注释和函数注释;用注释来说明我们的代码,也方便模块化开发,那么我们在写注释的时候经常会写一些重复的内容,我们会复制粘贴。这样一来二去,就显得很繁琐…...
docker 各种命令
-v 或 --volume 由三个由冒号(:)分隔的字段组成,[HOST-DIR:]CONTAINER-DIR[:OPTIONS]。 HOST-DIR 代表主机上的目录或数据卷的名字。省略该部分时,会自动创建一个匿名卷。如果是指定主机上的目录,需要使用绝对路径。 C…...
【优选算法系列】【专题五位运算】第一节.常见的位运算(面试题 01.01. 判定字符是否唯一和268. 丢失的数字)
文章目录 前言常见的位运算一、判定字符是否唯一 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写二、丢失的数字 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写总结 前言 常见的…...
学习笔记二十八:K8S控制器Daemonset入门到企业实战应用
DaemonSet控制器:概念、原理解读 DaemonSet概述DaemonSet工作原理:如何管理PodDaemonset典型的应用场景DaemonSet 与 Deployment 的区别DaemonSet资源清单文件编写技巧 DaemonSet使用案例:部署日志收集组件fluentdDaemonset管理pod࿱…...
您对互联网有多“上瘾”?
萨里大学的科学家决定检查现代用户的网络成瘾程度。他们的一篇文章最近发表在 《旅行与旅游营销杂志》上 ,其中包含对受此问题困扰的年轻人(而不仅仅是年轻人)的研究和分类结果。 796名不同年龄段的人参加了实验。科学家们仔细监测了他们的行…...
数据挖掘题目:设ε= 2倍的格网间距,MinPts = 6, 采用基于1-范数距离的DBSCAN算法对下图中的实心格网点进行聚类,并给出聚类结果(代码解答)
问题 代码 import matplotlib.pyplot as plt import numpy as np from sklearn.cluster import DBSCAN #pip install matplotlib #pip install numpy #pip install scikit-learn # 实心格网点的坐标 solid_points np.array([[1, 1], [2, 1],[3, 1], [1, 2], [2, 2], [3, 2],[…...
STM32HAL-完全解耦面向对象思维的架构-时间轮片法使用(timeslice)
目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、代码解释 六、总结 概述 timeslice是一个时间片轮询框架,完全解耦的时间片轮询框架,非常适合裸机单片机引用。接下来将该框架移植到stm32单片机运行,单片机…...
C++ 程序员入门需要多久,怎样才能学好?
我们都知道,C是所有语言的基础 !记得在大学毕业之后,做了C的后端开发当然还有一些嵌入式的相关的工作,到现在换工作,工作机会依然那么多,到了一定的阶段,我想你不是在找工作,而是工作…...
SpringBoot项目打war包部署到tomcat访问路径去掉项目名
方法一:手动修改包名 1.先将Tomcat webapp目录下文件全部删除 2.将war包文件放在webapps文件夹下 2.运行tomcat,war文件自动解压成文件夹 3.关闭tomcat,,将步骤2解压的文件夹直接改名为ROOT 4.重新运行tomcat,即可。 5…...
58同城面试
一、Java八股 1、ThreadLocal的底层原理是什么? ThreadLocal 在Java中用于提供线程局部变量,这些变量在每个线程中都有独立的副本,互不干扰。其底层原理可以简要描述如下: 数据存储: 每个线程中都有一个 ThreadLocalMap 的实例&…...
【数据结构】归并排序 的递归实现与非递归实现
归并排序 前言一、归并排序递归实现(1)归并排序的核心思路(2)归并排序实现的核心步骤(3)归并排序码源详解(4)归并排序效率分析1)时间复杂度 O(N*logN…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
