FCNTL(2) Linux Programmer's Manual FCNTL(2)
NAME
fcntl - manipulate file descriptor
//对fd操作
SYNOPSIS
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
DESCRIPTION
fcntl() performs one of the operations described below on the open file
descriptor fd. The operation is determined by cmd.
//fcntl()在已经打开的fd上执行下面描述的操作.操作由cmd定义.
fcntl() can take an optional third argument. Whether or not this argument is
required is determined by cmd. The required argument type is indicated in
parentheses after each cmd name (in most cases, the required type is long, and
we identify the argument using the name arg), or void is specified if the
argument is not required.
//fcntl()能够通过第三个参数进行操作,无论这个参数是否需要是由cmd决定的.需要的参数类型在
//每个cmd名字之后被指定(在大多数情况下,需要的数据类型是long,我们识别参数使用name),或者是
//一个void被指定如果参数不需要的话.
Duplicating a file descriptor
F_DUPFD (long)
Find the lowest numbered available file descriptor greater than or
equal to arg and make it be a copy of fd. This is different from
dup2(2), which uses exactly the descriptor specified.
//找到最低的,有限的,有效的fd大于等于arg,将arg最为fd的复制品.这和dup()不同,这使用精确指定
//的描述符
On success, the new descriptor is returned.
//成功:返回新的fd
See dup(2) for further details.
//更进一步的细节查看 dup(2)
F_DUPFD_CLOEXEC (long; since Linux 2.6.24)
As for F_DUPFD, but additionally set the close-on-exec flag for the
duplicate descriptor. Specifying this flag permits a program to avoid
an additional fcntl() F_SETFD operation to set the FD_CLOEXEC flag.
For an explanation of why this flag is useful, see the description of
O_CLOEXEC in open(2).
//为复制的描述符,对F_DUPFD 又加上 close-on-exec.指定这个标志位允许一个程序避免额外的
//fcntl()的F_SETFD操作来设置 FD_CLOEXEC . 为什么这个标志位是有用的,在open()中查看O_CLOEXEC
File descriptor flags
The following commands manipulate the flags associated with a file descriptor.
Currently, only one such flag is defined: FD_CLOEXEC, the close-on-exec flag.
If the FD_CLOEXEC bit is 0, the file descriptor will remain open across an
execve(2), otherwise it will be closed.
//下面的命令控制标志位与fd有关.当前,只有这样一个标志位定义了:FD_CLOEXEC(close-on-exec).
//如果FD_CLOEXEC位是0,那么fd将通过execve()来保持打开,不是0的话fd将关闭.
F_GETFD (void)
Read the file descriptor flags; arg is ignored.
//读fd,忽略arg
F_SETFD (long)
Set the file descriptor flags to the value specified by arg.
//将arg的值设置给fd
File status flags
Each open file description has certain associated status flags, initialized by
open(2) and possibly modified by fcntl(). Duplicated file descriptors (made
with dup(2), fcntl(F_DUPFD), fork(2), etc.) refer to the same open file
description, and thus share the same file status flags.
//每个打开的fd都有一定的关联状态标志位,由open()初始化可能被fcntl()更改.复制fd(使用dup(),
//fcntl(F_DUPFD), fork(2)等)使用相同的打开文件描述符,这样共享就有了相同的文件标志位.
The file status flags and their semantics are described in open(2).
//文件状态参数和它们的语义在open()中定义
F_GETFL (void)
Read the file status flags; arg is ignored.
//读fd,忽略arg
F_SETFL (long)
Set the file status flags to the value specified by arg. File access
mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags (i.e.,
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On Linux this
command can only change the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and
O_NONBLOCK flags.
//设置由arg指定的文件状态.文件访问模式()和文件创建标识()在arg是忽略的.在linux这个命令只能
//改变O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, 和O_NONBLOCK.
Advisory locking//咨询锁
F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and test for the
existence of record locks (also known as file-segment or file-region locks).
The third argument, lock, is a pointer to a structure that has at least the
following fields (in unspecified order).
//F_GETLK, F_SETLK 和 F_SETLKW是用来对应 获得 释放 测试 记录锁的存在(也知道文件段和文件域锁)
//第三个参数,锁,是指向一个结构体的指针,至少有下面的一些区域(未具体指出的顺序)
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) */
...
};
The l_whence, l_start, and l_len fields of this structure specify the range of
bytes we wish to lock. Bytes past the end of the file may be locked, but not
bytes before the start of the file.
//l_whence, l_start, 和 l_len指定锁定的域的字节数.文件之后的数据会被锁住,文件之前的就不会.
l_start is the starting offset for the lock, and is interpreted relative to
either: the start of the file (if l_whence is SEEK_SET); the current file
offset (if l_whence is SEEK_CUR); or the end of the file (if l_whence is
SEEK_END). In the final two cases, l_start can be a negative number provided
the offset does not lie before the start of the file.
//l_start对锁开始的offset的偏移,被解释跟另一个有关:文件的开头(如果l_start是SEEK_SET的话);
//当前文件的偏移(如果l_start是SEEK_CUR的话);后者是文件末尾(如果l_start是SEEK_END的话).
//在最后的2种情况下,l_start可以使用负数提供偏移不在文件开始之前.
l_len specifies the number of bytes to be locked. If l_len is positive, then
the range to be locked covers bytes l_start up to and including
l_start+l_len-1. Specifying 0 for l_len has the special meaning: lock all
bytes starting at the location specified by l_whence and l_start through to
the end of file, no matter how large the file grows.
//l_len指定要被锁定的字节数.如果l_len是正数,那么锁定的区域覆盖l_start到l_start + l_len - 1
//之间.指定0有特殊的含义:锁定所有由l_whence开始的数据,从l_start到文件结束,不管文件增长多大.
POSIX.1-2001 allows (but does not require) an implementation to support a
negative l_len value; if l_len is negative, the interval described by lock
covers bytes l_start+l_len up to and including l_start-1. This is supported
by Linux since kernel versions 2.4.21 and 2.5.49.
//POSIX.1-2001允许但是不是必须一个实现来支持负数的l_len值;如果l_len是负数,由锁描述的空间,
//就更新为从l_start+l_len 到 l_start-1 .这由linux的2.4.21到2.5.49的kernel支持的.
The l_type field can be used to place a read (F_RDLCK) or a write (F_WRLCK)
lock on a file. Any number of processes may hold a read lock (shared lock) on
a file region, but only one process may hold a write lock (exclusive lock).
An exclusive lock excludes all other locks, both shared and exclusive. A
single process can hold only one type of lock on a file region; if a new lock
is applied to an already-locked region, then the existing lock is converted to
the new lock type. (Such conversions may involve splitting, shrinking, or
coalescing with an existing lock if the byte range specified by the new lock
does not precisely coincide with the range of the existing lock.)
//l_type可以用来在文件上设置读写锁.一些进程可以在文件区域上保持写锁(共享锁),但是只有一个进程
//可以在一个文件上保持一个写锁(互斥锁).一个互斥锁排斥其他的任何锁,包括共享锁和互斥锁.
//单个的进程可以在文件区域上保持一种锁的类型,如果一个新锁施加于一个已经锁的区域,那么
//已经存在的锁就转换为新类型的锁.(这种转换应该是极快的,缩小的,或者是同已经存在的锁合并,
//如果被新锁锁定的区域的字节数没有精确的同已经存在的锁的区域一致的话)
F_SETLK (struct flock *)
Acquire a lock (when l_type is F_RDLCK or F_WRLCK) or release a lock
(when l_type is F_UNLCK) on the bytes specified by the l_whence,
l_start, and l_len fields of lock. If a conflicting lock is held by
another process, this call returns -1 and sets errno to EACCES or
EAGAIN.
//(当l_type 是 F_RDLCK 或者 F_WRLCK的时候)获得一个锁或者释放一个锁(当l_type 是 FF_UNLCK的时候).
//当由l_whence,l_start, 和 l_len指定的区域.如果一个冲突的锁被其他线程保持,这个调用返回-1,
//然后errno被设置为EACCES或EAGAIN.
F_SETLKW (struct flock *)
As for F_SETLK, but if a conflicting lock is held on the file, then
wait for that lock to be released. If a signal is caught while
waiting, then the call is interrupted and (after the signal handler has
returned) returns immediately (with return value -1 and errno set to
EINTR; see signal(7)).
//对F_SETLK而言,如果一个冲突的锁被文件保持,之后就等待这个锁被释放.如果在等待的时候一个信号
//被捕获,这么这个调用就中断,(当信号句柄返回之后)调用就立即返回(值为-1,errno为EINTR)
F_GETLK (struct flock *)
On input to this call, lock describes a lock we would like to place on
the file. If the lock could be placed, fcntl() does not actually place
it, but returns F_UNLCK in the l_type field of lock and leaves the
other fields of the structure unchanged. If one or more incompatible
locks would prevent this lock being placed, then fcntl() returns
details about one of these locks in the l_type, l_whence, l_start, and
l_len fields of lock and sets l_pid to be the PID of the process
holding that lock.
//对这个调用的输入,锁描述了一个我们应该替换在文件上的锁.如果锁能够被替换,fcntl()实际上并不
//替换它,在l_type的域返回F_UNLCK,结构体的其他成员不改变.如果一个或者多个不协调的锁阻止这个
//锁被替换,那么fcntl()就返回它们之间的一个锁的细节在l_type, l_whence, l_start, 和 l_len
//成员中,在l_pid中设置持有这个锁的进程的ID
In order to place a read lock, fd must be open for reading. In order to place
a write lock, fd must be open for writing. To place both types of lock, open
a file read-write.
//为了替换一个读锁,fd必须打开是为了读的,写锁同上.读写锁同上.
As well as being removed by an explicit F_UNLCK, record locks are
automatically released when the process terminates or if it closes any file
descriptor referring to a file on which locks are held. This is bad: it means
that a process can lose the locks on a file like /etc/passwd or /etc/mtab when
for some reason a library function decides to open, read and close it.
//为了移除明确的F_UNLCK,当进程中止的时候或者是记录锁被fd被持有锁的文件关闭的时候,那么
//记录锁就被自动释放.这是不好的:这就意味着一个进程可以关闭一个类似/etc/passwd 或 /etc/mtab
//上的锁,当因为一些原因一个库函数决定打开,读和关闭它们的时候.
Record locks are not inherited by a child created via fork(2), but are
preserved across an execve(2).
//记录锁是不能通过fork()创建的子进程继承的,但是通过execve()保持着
Because of the buffering performed by the stdio(3) library, the use of record
locking with routines in that package should be avoided; use read(2) and
write(2) instead.
//因为buf是被stdio库操作的,在程序中使用记录锁应该被避免,使用read()和write()来代替
Mandatory locking//强制的锁定
(Non-POSIX.) The above record locks may be either advisory or mandatory, and
are advisory by default.
//上面的记录锁不是警告就是强制性的,在default里公告.
Advisory locks are not enforced and are useful only between cooperating
processes.
//警告锁不是强制的,仅仅在合作的进程间是有用的.
Mandatory locks are enforced for all processes. If a process tries to perform
an incompatible access (e.g., read(2) or write(2)) on a file region that has
an incompatible mandatory lock, then the result depends upon whether the
O_NONBLOCK flag is enabled for its open file description. If the O_NONBLOCK
flag is not enabled, then system call is blocked until the lock is removed or
converted to a mode that is compatible with the access. If the O_NONBLOCK
flag is enabled, then the system call fails with the error EAGAIN.
//强制锁对所有的线程都是强制的.如果一个进程尝试在一个文件区域内执行一个不合适的访问(例如读写),
//那就有一个不合适的强制锁.那么结果就取决于是否O_NONBLOCK被使能,之后系统调用就被阻塞直到
//锁被移除或者是转换为对访问合适的模式.如果O_NONBLOCK被使能,系统调用失败返回error为EAGAIN.
To make use of mandatory locks, mandatory locking must be enabled both on the
file system that contains the file to be locked, and on the file itself.
Mandatory locking is enabled on a file system using the "-o mand" option to
mount(8), or the MS_MANDLOCK flag for mount(2). Mandatory locking is enabled
on a file by disabling group execute permission on the file and enabling the
set-group-ID permission bit (see chmod(1) and chmod(2)).
//为了充分使用强制锁,锁必须既在包含锁定文件的文件系统中使能,也在文件自身使能.
//强制锁使用mount的"-o mand"来打开文件系统的使能,或者是mount()的MS_MANDLOCK标志位.
//强制锁在文件上的使能通过禁止组执行权限和使能设置组ID的权限位.
The Linux implementation of mandatory locking is unreliable. See BUGS below.
//linux对强制锁的实现是不可靠的,参加bug.>>>>>日,说了这么多有bug......
Managing signals//信号管理
F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG and F_SETSIG are used
to manage I/O availability signals:
F_GETOWN (void)
Return (as the function result) the process ID or process group
currently receiving SIGIO and SIGURG signals for events on file
descriptor fd. Process IDs are returned as positive values; process
group IDs are returned as negative values (but see BUGS below). arg is
ignored.
//返回进程ID或者进程组当前接收到对在fd的事件SIGIO和SIGURG信号.进程ID返回正值,
//进程组ID返回负值(参见下面的bug).arg被忽略.
F_SETOWN (long)
Set the process ID or process group ID that will receive SIGIO and
SIGURG signals for events on file descriptor fd to the ID given in arg.
A process ID is specified as a positive value; a process group ID is
specified as a negative value. Most commonly, the calling process
specifies itself as the owner (that is, arg is specified as getpid(2)).
//设置进程ID或者进程组将接收到的由arg指定的ID上的fd的事件的SIGIO和SIGURG信号.进程ID由正值
//指定,组ID由负值指定.最经常的,调用进程指定它自己作为拥有者(arg由getpid()指定).
If you set the O_ASYNC status flag on a file descriptor by using the
F_SETFL command of fcntl(), a SIGIO signal is sent whenever input or
output becomes possible on that file descriptor. F_SETSIG can be used
to obtain delivery of a signal other than SIGIO. If this permission
check fails, then the signal is silently discarded.
//使用fcntl()的F_SETFL命令打开的fd上设置了O_ASYNC状态,在fd上不管是输入还是输出,一个
//SIGIO信号总是被发送.F_SETSIG用来分离一个信号而不是SIGIO.如果这个权限检验失败,信号被默默的丢弃.
Sending a signal to the owner process (group) specified by F_SETOWN is
subject to the same permissions checks as are described for kill(2),
where the sending process is the one that employs F_SETOWN (but see
BUGS below).
//向一个由F_SETOWN指定的拥有者线程发送信号是与受到使用kill()相同权限检查的一致的.
//发送信号的线程是使用F_SETOWN标志位的(bug在下面)
If the file descriptor fd refers to a socket, F_SETOWN also selects the
recipient of SIGURG signals that are delivered when out-of-band data
arrives on that socket. (SIGURG is sent in any situation where
select(2) would report the socket as having an "exceptional
condition".)
//如果fd 是socket的描述符,F_SETOWN 仍然选择当在socket上接收的数据超过带宽的 SIGURG 信号的容器.
//(SIGURG 会在当select(2)报告socket发生一个异常的时候会被发送)
The following was true in 2.6.x kernels up to and including kernel
2.6.11:
//下面这些是真实的在2.6.X版本上,包括2.6.11
If a nonzero value is given to F_SETSIG in a multithreaded
process running with a threading library that supports thread
groups (e.g., NPTL), then a positive value given to F_SETOWN has
a different meaning: instead of being a process ID identifying a
whole process, it is a thread ID identifying a specific thread
within a process. Consequently, it may be necessary to pass
F_SETOWN the result of gettid(2) instead of getpid(2) to get
sensible results when F_SETSIG is used. (In current Linux
threading implementations, a main thread's thread ID is the same
as its process ID. This means that a single-threaded program
can equally use gettid(2) or getpid(2) in this scenario.) Note,
however, that the statements in this paragraph do not apply to
the SIGURG signal generated for out-of-band data on a socket:
this signal is always sent to either a process or a process
group, depending on the value given to F_SETOWN.
//在一个支持线程组的线程库(如NTPL)中运行多线程程序,当一个非零值给了F_SETSIG 的时候,负值给了 F_SETOWN 会有一个不同的意义
//进程ID不再用来识别一整个进程,而是识别进程的一个特定线程.因此,当使用F_SETSIG 的时候就需要向F_SETOWN 传递 gettid(2)的返回值而不是 getpid(2)的才是明智的
//(当前linux 多线程程序,main()的线程ID和它的进程ID是相同的,这就意味着单线程的程序使用gettid(2)和getpid(2)在这种情况是等同的)
//注意:然而在本章的情况下,并不适用于在一个超过带宽的socket下产生SIGURG信号:这个信号总是要么发送给一个进程或者是进程组
//这取决于F_SETOWN 的值
The above behavior was accidentally dropped in Linux 2.6.12, and won't
be restored. From Linux 2.6.32 onward, use F_SETOWN_EX to target SIGIO
and SIGURG signals at a particular thread.
//上面这种情况很偶然的出现在2.6.12,不能被恢复.从linux2.6.32之前,使用 F_SETOWN 在特定的进程中来定位 SIGIO 和 SIGURG.
F_GETOWN_EX (struct f_owner_ex *) (since Linux 2.6.32)
Return the current file descriptor owner settings as defined by a
previous F_SETOWN_EX operation. The information is returned in the
structure pointed to by arg, which has the following form:
//F_GETOWN_EX(struct f_owner_ex *)在linux2.6.32之后
//返回之前使用F_SETOWN_EX定义的当前fd的拥有者设置,返回的信息是由以下结构的arg指向的结构体定义的
struct f_owner_ex {
int type;
pid_t pid;
};
The type field will have one of the values F_OWNER_TID, F_OWNER_PID, or
F_OWNER_PGRP. The pid field is a positive integer representing a
thread ID, process ID, or process group ID. See F_SETOWN_EX for more
details.
//type 元素是以下几个值之一: F_OWNER_TID, F_OWNER_PID, F_OWNER_PGRP
//pid 是一个正整数来表示进程ID,线程ID,或者进程组ID,在F_SETOWN_EX看更多的细节
F_SETOWN_EX (struct f_owner_ex *) (since Linux 2.6.32)
This operation performs a similar task to F_SETOWN. It allows the
caller to direct I/O availability signals to a specific thread,
process, or process group. The caller specifies the target of signals
via arg, which is a pointer to a f_owner_ex structure. The type field
has one of the following values, which define how pid is interpreted:
//F_SETOWN_EX (struct f_owner_ex *) 从 Linux 2.6.32 之后)
//这个操作和F_SETOWN很像,它允许调用者在指定的线程,进程,或进程组中指挥有效的IO信号.
//调用者通过一个指向f_owner_ex结构体的arg来指定信号的目标.
//type 有其中的一个值:定义了pid是如何被中断的
F_OWNER_TID
Send the signal to the thread whose thread ID (the value
returned by a call to clone(2) or gettid(2)) is specified in
pid.
//向线程ID(由clone(2)或者getpid(2)获取)和由pid相等的线程发送信号.
F_OWNER_PID
Send the signal to the process whose ID is specified in pid.
//向由pid指定的进程ID发送信号
F_OWNER_PGRP
Send the signal to the process group whose ID is specified in
pid. (Note that, unlike with F_SETOWN, a process group ID is
specified as a positive value here.)
//向由pid指定的进程组ID发送信号(注意:和F_SETOWN不同,进程组ID由一个正整数在这里指定)
F_GETSIG (void)
Return (as the function result) the signal sent when input or output
becomes possible. A value of zero means SIGIO is sent. Any other
value (including SIGIO) is the signal sent instead, and in this case
additional info is available to the signal handler if installed with
SA_SIGINFO. arg is ignored.
//当输入和输出变得可能时返回(作为函数的返回值)发送的信号.0值意味着SIGIO被发送了,其他值
//(包含SIGUO)的信号被发送了,在这种情况下,对信号处理程序而言进一步有用的信息是:
//如果设置了SA_SIGINFO 那么arg就会会忽略
F_SETSIG (long)
Set the signal sent when input or output becomes possible to the value
given in arg. A value of zero means to send the default SIGIO signal.
Any other value (including SIGIO) is the signal to send instead, and in
this case additional info is available to the signal handler if
installed with SA_SIGINFO.
//当输入或者输出变得可能的时候发送由arg指定的信号.0值意味着发送了默认的SIGIO信号,
//其他值(包好SIGIO)的信号被发送了,在这种情况下,对信号处理程序而言进一步有用的信息是有效的
//如果设置了SA_SIGINFO.
By using F_SETSIG with a nonzero value, and setting SA_SIGINFO for the
signal handler (see sigaction(2)), extra information about I/O events
is passed to the handler in a siginfo_t structure. If the si_code
field indicates the source is SI_SIGIO, the si_fd field gives the file
descriptor associated with the event. Otherwise, there is no
indication which file descriptors are pending, and you should use the
usual mechanisms (select(2), poll(2), read(2) with O_NONBLOCK set etc.)
to determine which file descriptors are available for I/O.
//当使用F_SETSIG时为非零值时,并且信号处理程序设置到了SA_SIGINFO(参见 sigaction(2)),通过
//siginfo_t结构体就会将额外的IO事件信息传递给信号处理程序,si_fd 定义了与事件相关的fd信息.
//否则,没有迹象表明哪个fd是未决定的,你必须使用常见的机制(select(2), poll(2), read(2) 配合O_NONBLOCK设置等等)
//来决定哪个fd是对IO有效的
By selecting a real time signal (value >= SIGRTMIN), multiple I/O
events may be queued using the same signal numbers. (Queuing is
dependent on available memory). Extra information is available if
SA_SIGINFO is set for the signal handler, as above.
//当选择一个实际时间的信号(value >= SIGRTMIN),多IO事件可能使用相同的信号值来进行排队.
//(队列依赖于有效的内存).额外的信息是有效的如果对信号处理程序设置SA_SIGINFO的话,像上面的那样
Note that Linux imposes a limit on the number of real-time signals that
may be queued to a process (see getrlimit(2) and signal(7)) and if this
limit is reached, then the kernel reverts to delivering SIGIO, and this
signal is delivered to the entire process rather than to a specific
thread.
//注意:在real-time信号的值上,linux做了一个欺骗,在进程排队的时候(见getrlimit(2) 和 signal(7))
//当real-time的值到达了限制值的时候,内核恢复释放的SIGIO,这个信号被发送到整个进程而不是一个特定的线程(翻译的不好??)
Using these mechanisms, a program can implement fully asynchronous I/O without
using select(2) or poll(2) most of the time.
//使用这些结构,在大多数时候程序可以实现完全的同步IO而不使用select(2)或者poll(2).
The use of O_ASYNC, F_GETOWN, F_SETOWN is specific to BSD and Linux.
F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, and F_SETSIG are Linux-specific. POSIX
has asynchronous I/O and the aio_sigevent structure to achieve similar things;
these are also available in Linux as part of the GNU C Library (Glibc).
//O_ASYNC, F_GETOWN, F_SETOWN 只在BSD 和 Linux 上使用.
//F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, 和 F_SETSIG是Linux 专用的.
//POSIX 也有同步的IO,使用aio_sigevent结构体来实现类似的事情;
//作为GNU C 库的一部分(Glibc),POSIX 的内容在linux下也是有效的.
Leases
F_SETLEASE and F_GETLEASE (Linux 2.4 onward) are used (respectively) to
establish a new lease, and retrieve the current lease, on the open file
description referred to by the file descriptor fd. A file lease provides a
mechanism whereby the process holding the lease (the "lease holder") is
notified (via delivery of a signal) when a process (the "lease breaker") tries
to open(2) or truncate(2) the file referred to by that file descriptor.
//对有fd指定的文件描述符而言,F_SETLEASE 和 F_GETLEASE(Linux 2.4之前)分别用来建立一个租期和取回当前的租期的.
//对有fd指定的文件描述符而言,一个文件租期提供一个机制,因此当一个进程(租期破坏者)试图打开或者阶段fd的时候
//进程保持这租期(租期持有者)(通过传递信号)来监视.
F_SETLEASE (long)
Set or remove a file lease according to which of the following values
is specified in the integer arg:
//根据下面指定的整数arg参数来设置或者溢出一个文件租期
F_RDLCK
Take out a read lease. This will cause the calling process to
be notified when the file is opened for writing or is truncated.
A read lease can only be placed on a file descriptor that is
opened read-only.
//取出读租期.当文件被打开或者正在写入或被截断的时候,调用线程就会被监视.
//读租期可以仅仅设置在一个打开的只读的fd.
F_WRLCK
Take out a write lease. This will cause the caller to be
notified when the file is opened for reading or writing or is
truncated. A write lease may be placed on a file only if there
are no other open file descriptors for the file.
//取出写租期.当文件被打开或者正在读取或被截断的时候,调用线程就会被监视.
//读租期可以设置在一个没有别的打开的fd的文件上
F_UNLCK
Remove our lease from the file.
//从文件上移除别的租期
Leases are associated with an open file description (see open(2)). This means
that duplicate file descriptors (created by, for example, fork(2) or dup(2))
refer to the same lease, and this lease may be modified or released using any
of these descriptors. Furthermore, the lease is released by either an
explicit F_UNLCK operation on any of these duplicate descriptors, or when all
such descriptors have been closed.
//租期和一个打开的fd有关.这就意味着复制fd(例如由fork(2) 或 dup(2)来创建的)也有着相同的租期.,
//并且租期也可以被这些复制的fd来进行和释放.此外,租期可以被(源fd或者复制的fd)明确的F_UNLCK操作
//或者是这些fd关闭的时候来释放.
Leases may only be taken out on regular files. An unprivileged process may
only take out a lease on a file whose UID (owner) matches the file system UID
of the process. A process with the CAP_LEASE capability may take out leases
on arbitrary files.
//租期只能被普通的文件取出.一个没有特权的进程可以仅仅取出一个文件的UID和系统的UID相同的租期.
//有CAP_LEASE能力的进程可以出去任意文件的租期.
F_GETLEASE (void)
Indicates what type of lease is associated with the file descriptor fd
by returning either F_RDLCK, F_WRLCK, or F_UNLCK, indicating,
respectively, a read lease , a write lease, or no lease. arg is
ignored.
//与之相关的fd返回F_RDLCK, F_WRLCK, 或 F_UNLCK 分别读的租期,写的租期或没有租期.
//参数arg被忽略
When a process (the "lease breaker") performs an open(2) or truncate(2) that
conflicts with a lease established via F_SETLEASE, the system call is blocked
by the kernel and the kernel notifies the lease holder by sending it a signal
(SIGIO by default). The lease holder should respond to receipt of this signal
by doing whatever cleanup is required in preparation for the file to be
accessed by another process (e.g., flushing cached buffers) and then either
remove or downgrade its lease. A lease is removed by performing an F_SETLEASE
command specifying arg as F_UNLCK. If the lease holder currently holds a
write lease on the file, and the lease breaker is opening the file for
reading, then it is sufficient for the lease holder to downgrade the lease to
a read lease. This is done by performing an F_SETLEASE command specifying arg
as F_RDLCK.
//当一个进程(租期破坏者)使用open(2) 或 truncate(2)和一个明确的使用F_SETLEASE的租期冲突的时候,
//内核就会通过发送一个信号(SIGIO 默认)来监视租期的持有者,并且阻塞这个系统调用.
//租期的持有者应该通过进行必要的清理准备工作(冲刷缓冲了的缓存,之后取出或者降低租期)来回应接到信号的进程.
//租期由通过指定的值为F_UNLCK的arg参数调用F_SETLEASE来移除.如果租期的持有者当前持有一个文件的写租期,
//而租期的破坏者当前持有一个文件的读租期,那么租期的持有者就有充分的理由来降低读租期.
//这是由通过指定的值为 F_RDLCK 的arg参数调用 F_SETLEASE 来实现的.
If the lease holder fails to downgrade or remove the lease within the number
of seconds specified in /proc/sys/fs/lease-break-time then the kernel forcibly
removes or downgrades the lease holder's lease.
//如果租期的持有者在/proc/sys/fs/lease-break-time 指定的秒数内不能成功的降低或者移除租期,
//之后内核就会强制的移除或者降低持有者的租期
Once the lease has been voluntarily or forcibly removed or downgraded, and
assuming the lease breaker has not unblocked its system call, the kernel
permits the lease breaker's system call to proceed.
//一旦租期被自动或者强制地被移除或降低,内核允许租期破坏者来处理.
If the lease breaker's blocked open(2) or truncate(2) is interrupted by a
signal handler, then the system call fails with the error EINTR, but the other
steps still occur as described above. If the lease breaker is killed by a
signal while blocked in open(2) or truncate(2), then the other steps still
occur as described above. If the lease breaker specifies the O_NONBLOCK flag
when calling open(2), then the call immediately fails with the error
EWOULDBLOCK, but the other steps still occur as described above.
//如果租期破坏者被信号而阻塞在了open(2)或者是truncate(2),那么系统调用失败返回错误号EINTR,
//但是其他的步骤始终会像以上描述的那样发生.如果租期破坏者当阻塞在open(2)或者是truncate(2)的
//时候被信号给kill掉了,其他的步骤始终会像以上描述的那样发生.如果租期破坏者调用open(2)时被O_NONBLOCK指定,
//那么调用会立即失败并返回错误号EWOULDBLOCK,其他的步骤始终会像以上描述的那样发生.
The default signal used to notify the lease holder is SIGIO, but this can be
changed using the F_SETSIG command to fcntl(). If a F_SETSIG command is
performed (even one specifying SIGIO), and the signal handler is established
using SA_SIGINFO, then the handler will receive a siginfo_t structure as its
second argument, and the si_fd field of this argument will hold the descriptor
of the leased file that has been accessed by another process. (This is useful
if the caller holds leases against multiple files).
//默认监视租期程序的信号是SIGIO,但是使用fcntl()的 F_SETSIG 命令可以改变.如果F_SETSIG命令已经运行(即使制定了SIGIO),
//同时信号处理程序确定的使用SA_SIGINFO,之后信号处理程序会接收到siginfo_t结构体作为第二参数,
//这个参数的si_fd域将会锁定被别的进程访问的租用文件的fd(这会很有用的如果调用租期的程序和多个文件冲突的话?).
File and directory change notification (dnotify)//文件和目录改变通知
F_NOTIFY (long)
(Linux 2.4 onward) Provide notification when the directory referred to
by fd or any of the files that it contains is changed. The events to
be notified are specified in arg, which is a bit mask specified by
ORing together zero or more of the following bits:
//(Linux 2.4 之前的)提供通知当由fd指定的目录或者文件改变的时候.被监视的事件有arg参数指定的
//由0或者是下面的几个ORing一起指定的掩码.
DN_ACCESS A file was accessed (read, pread, readv)
//文件被访问
DN_MODIFY A file was modified (write, pwrite, writev, truncate,
ftruncate).
//文件被修改
DN_CREATE A file was created (open, creat, mknod, mkdir, link,
symlink, rename).
//文件被创建
DN_DELETE A file was unlinked (unlink, rename to another directory,
rmdir).
//文件被取消链接(unlink,重命名为另一个文件夹,rmdir)
DN_RENAME A file was renamed within this directory (rename).
//在本文件夹内重命名 DN_ATTRIB The attributes of a file were changed (chown, chmod, utime[s]). //改变文件属性 (In order to obtain these definitions, the _GNU_SOURCE feature test macro must be defined before including any header files.) //为了获得这些定义,在包含任何的头文件前_GNU_SOURCE特性测试宏必须定义. Directory notifications are normally "one-shot", and the application must reregister to receive further notifications. Alternatively, if DN_MULTISHOT is included in arg, then notification will remain in effect until explicitly removed. //文件夹通知一般都是一次性的,程序必须注册来接收下个通知.二选一的,arg 参数中包含DN_MULTISHOT,
//直到明确的去除设置,那么通知就会一直有效. A series of F_NOTIFY requests is cumulative, with the events in arg being added to the set already monitored. To disable notification of all events, make an F_NOTIFY call specifying arg as 0. //当arg参数中已经设置了监视F_NOTIFY的时候,大量的F_NOTIFY请求会被累加.为了禁止所有事件的通知,
//使用F_NOTIFY调用并且arg为0. Notification occurs via delivery of a signal. The default signal is SIGIO, but this can be changed using the F_SETSIG command to fcntl(). In the latter case, the signal handler receives a siginfo_t structure as its second argument (if the handler was established using SA_SIGINFO) and the si_fd field of this structure contains the file descriptor which generated the notification (useful when establishing notification on multiple directories). //通知的产生是用过信号的传送的.默认的信号是SIGIO,但是这可以通过fcntl()的F_SETSIG命令改变.
//在F_SETSIG情况下,信号处理程序接收到siginfo_t的结构体作为第二参数(如果信号处理程序明确的使用SA_SIGINFO),
//并且结构体的si_fd的域包含着产生通知的文件的fd(很有用在多文件夹上有明确通知的时候). Especially when using DN_MULTISHOT, a real time signal should be used for notification, so that multiple notifications can be queued. //例外的当使用DN_MULTISHOT的时候,通知就使用一个实时的信号,导致多个通知会被排队. NOTE: New applications should use the inotify interface (available since kernel 2.6.13), which provides a much superior interface for obtaining notifications of file system events. See inotify(7).
//注意:新程序应该使用inotify接口(在2.6.13之后),这个接口提供了更好的获取文件系统事件改变的通知方式.
//对inotify可以参考以下一篇文章
//http://www.ibm.com/developerworks/cn/linux/l-inotifynew/index.html
Changing the capacity of a pipe//改变管道的容量
F_SETPIPE_SZ (long; since Linux 2.6.35)
Change the capacity of the pipe referred to by fd to be at least arg
bytes. An unprivileged process can adjust the pipe capacity to any
value between the system page size and the limit defined in
/proc/sys/fs/pipe-size-max (see proc(5)). Attempts to set the pipe
capacity below the page size are silently rounded up to the page size.
Attempts by an unprivileged process to set the pipe capacity above the
limit in /proc/sys/fs/pipe-size-max yield the error EPERM; a privileged
process (CAP_SYS_RESOURCE) can override the limit. When allocating the
buffer for the pipe, the kernel may use a capacity larger than arg, if
that is convenient for the implementation. The F_GETPIPE_SZ operation
returns the actual size used. Attempting to set the pipe capacity
smaller than the amount of buffer space currently used to store data
produces the error EBUSY.
//至少改变由fd指定的通道的容量arg个字节.没有特权的进程可以在系统页大小和由/proc/sys/fs/pipe-size-max (参见 proc(5))
//规定的值之间调整管道的大小.尝试设置管道大小在页大小以下会静默的围拢成为页的大小.
//没有特权的进程尝试设置管道大小在/proc/sys/fs/pipe-size-max域的限制的话会导致EPERM的错误;
//特权进程(CAP_SYS_RESOURCE)可以超过这个限制.
//当为管道分配缓存时,内核可能会使用比arg大的容量,如果对程序而言方便的话.
//F_GETPIPE_SZ操作返回世界使用的大小.
//尝试设置管道大小小于当前用于存储数据的缓存空间数量的话会导致EBUSY错误.
F_GETPIPE_SZ (void; since Linux 2.6.35)//在2.6.35之后
Return (as the function result) the capacity of the pipe referred to by
fd.
//返回被fd在制定的管道的容量(作为函数的结果).
RETURN VALUE
For a successful call, the return value depends on the operation: //这些操作将会返回成功的调用 F_DUPFD The new descriptor. //新的fd F_GETFD Value of flags. //flags的值--这里写错了,应该是fd的值,而不是flags的值,是的话和下面的重复,这里man手册错了 F_GETFL Value of flags. //flags的制 F_GETLEASE Type of lease held on file descriptor. //fd租期的属性 F_GETOWN Value of descriptor owner. //fd所有者的属性 F_GETSIG Value of signal sent when read or write becomes possible, or zero for traditional SIGIO behavior. //当读写变为可能时,0或者是SIGIO返回的值 F_GETPIPE_SZ The pipe capacity. //管道的容量 All other commands Zero. //其他命令返回0 On error, -1 is returned, and errno is set appropriately. //错误的话返回-1,errno自动设定
ERRORS
EACCES or EAGAIN
Operation is prohibited by locks held by other processes.
//操作被其他进程的锁所阻止
EAGAIN The operation is prohibited because the file has been memory-mapped by
another process.
//因为文件被别的进程内存映射了,所以操作被阻止了
EBADF fd is not an open file descriptor, or the command was F_SETLK or
F_SETLKW and the file descriptor open mode doesn't match with the type
of lock requested.
//fd不是一个打开的文件描述符,或者命令是F_SETLKW而fd打开模式和所锁的模式不匹配
EDEADLK
It was detected that the specified F_SETLKW command would cause a
deadlock.
//检测到F_SETLKW命令会导致死锁
EFAULT lock is outside your accessible address space.
//锁在你可以访问的地址之外
EINTR For F_SETLKW, the command was interrupted by a signal; see signal(7).
For F_GETLK and F_SETLK, the command was interrupted by a signal before
the lock was checked or acquired. Most likely when locking a remote
file (e.g., locking over NFS), but can sometimes happen locally.
//对F_SETLKW,命令被信号打断.参见signal(7).
//多F_GETLK 和 F_SETLK,在锁被检测或获得前就被信号打断.
//就像锁定一个远程的文件一样(从nfs锁定),但是有时也会在本地发生.
EINVAL For F_DUPFD, arg is negative or is greater than the maximum allowable
value. For F_SETSIG, arg is not an allowable signal number.
//对F_DUPFD而言,arg是负数,或者比允许的最大值还大.
//F_SETSIG而言,arg是不允许的值.
EMFILE For F_DUPFD, the process already has the maximum number of file
descriptors open.
//对F_DUPFD而言,进程已经有了最大的打开的fd
ENOLCK Too many segment locks open, lock table is full, or a remote locking
protocol failed (e.g., locking over NFS).
//太多的锁打开了,锁列表已经满了,或者是一个远程的锁协议失败(例如通过nfs的锁操作)
EPERM Attempted to clear the O_APPEND flag on a file that has the append-only
attribute set.
//在一个仅仅有O_APPEND属性的文件上想清除O_APPEND属性
CONFORMING TO//一致性
SVr4, 4.3BSD, POSIX.1-2001. Only the operations F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK and F_SETLKW, are specified in POSIX.1-2001. F_GETOWN and F_SETOWN are specified in POSIX.1-2001. (To get their definitions, define BSD_SOURCE, or _XOPEN_SOURCE with the value 500 or greater, or define _POSIX_C_SOURCE with the value 200809L or greater.) F_DUPFD_CLOEXEC is specified in POSIX.1-2008. (To get this definition, define _POSIX_C_SOURCE with the value 200809L or greater, or _XOPEN_SOURCE with the value 700 or greater.) F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE, and F_SETLEASE are Linux-specific. (Define the _GNU_SOURCE macro to obtain these definitions.)
NOTES
The errors returned by dup2(2) are different from those returned by F_DUPFD. //从dup2(2)返回的错误和使用F_DUPFD返回的是不一致的 Since kernel 2.0, there is no interaction between the types of lock placed by flock(2) and fcntl(). //从kernel 2.0之后,flock(2) 和 fcntl()之间就不再有锁类型的相互作用了 Several systems have more fields in struct flock such as, for example, l_sysid. Clearly, l_pid alone is not going to be very useful if the process holding the lock may live on a different machine.
//在一些系统中flock结构有着更多的域,如l_sysid.清楚的是,如果进程持有着别的设备的锁的话,
//单独的l_sysid就不是很有用了
BUGS
A limitation of the Linux system call conventions on some architectures
(notably i386) means that if a (negative) process group ID to be returned by
F_GETOWN falls in the range -1 to -4095, then the return value is wrongly
interpreted by glibc as an error in the system call; that is, the return value
of fcntl() will be -1, and errno will contain the (positive) process group ID.
The Linux-specific F_GETOWN_EX operation avoids this problem. Since glibc
version 2.11, glibc makes the kernel F_GETOWN problem invisible by
implementing F_GETOWN using F_GETOWN_EX.
//在一些体系结构(在i386上尤其显著)的Linux系统调用规定的限制是,如果一个(负)线程组ID被F_GETOWN
//调用返回的话,范围是-1到-4095,那么在系统调用中返回值会最为错误被glibc打断;也就是说,
//fcntl()的返回值会是-1,errno会包含着负线程组ID的值.
//Linux 特定的 F_GETOWN_EX操作避免了这个问题,直到glibc 2.11之前(也就是2.11之后),glibc 使用
//F_GETOWN_EX来实现F_GETOWN以解决内核的F_GETOWN问题.
In Linux 2.4 and earlier, there is bug that can occur when an unprivileged
process uses F_SETOWN to specify the owner of a socket file descriptor as a
process (group) other than the caller. In this case, fcntl() can return -1
with errno set to EPERM, even when the owner process (group) is one that the
caller has permission to send signals to. Despite this error return, the file
descriptor owner is set, and signals will be sent to the owner.
//在Linux 2.4和之前,当一个无特权的线程使用F_SETOWN来指定一个socket类型的fd的拥有者为进程(组)
//而不是调用者的时候,就会发生bug.在这种情况下,fcntl()会返回-1同时errno置为EPERM,甚至当拥有者
//进程(组)是调用者之一,fcntl()有权发送信号.尽管错误返回,fd的拥有者被设置了,信号会发给拥有者
The implementation of mandatory locking in all known versions of Linux is
subject to race conditions which render it unreliable: a write(2) call that
overlaps with a lock may modify data after the mandatory lock is acquired; a
read(2) call that overlaps with a lock may detect changes to data that were
made only after a write lock was acquired. Similar races exist between
mandatory locks and mmap(2). It is therefore inadvisable to rely on mandatory
locking.
//在所有已知的Linux版本中,强制锁的实现都是受制于竞争条件的,这就使得其不可靠:
//在强制锁获得后write(2)调用会覆盖一个锁从而修改数据;
//在写操作锁获得后read(2)调用会覆盖一个锁从而检查数据的更改;
//类似的竞争存在于强制锁和mmap(2)之间.
//因此以来于强制锁的操作是不明智的.
SEE ALSO
dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7) See also locks.txt, mandatory-locking.txt, and dnotify.txt in the kernel source directory Documentation/filesystems/. (On older kernels, these files are directly under the Documentation/ directory, and mandatory-locking.txt is called mandatory.txt.)
COLOPHON
This page is part of release 3.29 of the Linux man-pages project. A
description of the project, and information about reporting bugs, can be found
at http://www.kernel.org/doc/man-pages/.
Linux 2010-09-10 FCNTL(2)
本文详细介绍了Linux系统调用fcntl()的使用方法及功能,包括文件描述符操作、文件状态标志设置、锁操作等内容。
1523

被折叠的 条评论
为什么被折叠?



