文件描述符
在Unix和Unix-like操作系统中,文件描述符(file descriptor, FD)是一个文件或者像pipe或者network socket等之类的输入/输出源的唯一标识。
文件描述符通常是一个非负整数,负数通常代表无值或者错误。
文件描述符是POSIX API的一部分。每个除deamons之外的进程都有三个标准的POSIX文件描述符,对应三个标准流:
概述
在Unix传统实现中,文件描述符索引到每个进程文件描述符表中,该表有内核维护,并索引到所有进程打开的系统范围的文件表中。文件表中记录有文件或其他资源打开的模式如读取、写入、追加以及其他可能模式。它还索引到称之为inode表的第三张表,inode表描述了实际的底层文件。
为了执行输入或输出,进程通过系统调用将文件描述符传给内核,内核将代表进程访问文件,进行不能直接访问文件或inode表。
在Linux中,进程打开的文件描述符可以通过/proc/PID/fd/路径来查看,其中PID表示进程id.
在Unix-like系统中,文件描述符可以指文件系统中命名的文件类型。除了常规文件,它还包括目录、块、字符设备、Unix域套接字和命名管道。文件描述符还可以指在文件系统中通常不存在的对象,如匿名管道和网络套接字。
C标准I/O库中的FILE数据结构通常包括类 Unix 系统上所讨论对象的低级文件描述符。整个数据结构提供了额外的抽象,被称为文件句柄。
对文件描述符的操作
下面列出在现代Unix-like系统中对文件描述符的典型操作。绝大多数函数在<unistd.h>头文件中声明,但也有一些在<fcntl.h>中
创建
open()creat()socket()accept()socketpair()pipe()epoll_create() (Linux)signalfd() (Linux)eventfd() (Linux)timerfd_create() (Linux)memfd_create() (Linux)userfaultfd() (Linux)fanotify_init() (Linux)inotify_init() (Linux)clone() (with flag CLONE_PIDFD, Linux)pidfd_open() (Linux)open_by_handle_at() (Linux)
导出
dirfd()fileno()
单个文件描述的操作
read(), write()readv(), writev()pread(), pwrite()recv(), send()recvfrom(), sendto()recvmsg(), sendmsg() (also used for sending FDs to other processes over a Unix domain socket)recvmmsg(), sendmmsg()lseek(), llseek()fstat()fstatvfs()fchmod()fchown()ftruncate()fsync()fdatasync()fdopendir()fgetxattr(), fsetxattr() (Linux)flistxattr(), fremovexattr() (Linux)statx (Linux)setns (Linux)vmsplice() (Linux)pidfd_send_signal() (Linux)waitid() (with P_PIDFD ID type, Linux)fdopen() (stdio function:converts file descriptor to FILE*)dprintf() (stdio function: prints to file descriptor)
Operations on multiple file descriptors
select(), pselect()poll(), ppoll()epoll_wait(), epoll_pwait(), epoll_pwait2() (Linux, takes a single epoll filedescriptor to wait on many other file descriptors)epoll_ctl() (for Linux)kqueue() (for BSD-based systems).sendfile()splice(), tee() (for Linux)copy_file_range() (for Linux)close_range() (for Linux)
Operations on the file descriptor table
fcntl()函数根据传入的命令参数,可以对文件描述执行不同的操作。这行命令获取/设置文件描述符关联的属性,包括F_GETFD, F_SETFD, F_GETFL and F_SETFL.
close()closefrom() (BSD and Solaris only; deletes all file descriptors greater than or equal to specified number)dup() (duplicates an existing file descriptor guaranteeing to be the lowest number available file descriptor)dup2(), dup3() (Close fd1 if necessary, and make file descriptor fd1 point to the open file of fd2)fcntl (F_DUPFD)
Operations that modify process state
fchdir() (sets the process’s current working directory based on a directory file descriptor)mmap() (maps ranges of a file into the process’s address space)
File locking
flock()fcntl() (F_GETLK, F_SETLK and F_SETLKW)lockf()
Sockets
See also: Berkeley sockets
connect()bind()listen()accept() (creates a new file descriptor for an incoming connection)getsockname()getpeername()getsockopt()setsockopt()shutdown() (shuts down one or both halves of a full duplex connection)
Miscellaneous
ioctl() (a large collection of miscellaneous operations on a single file descriptor, often associated with a device)
Upcoming operations
A series of new operations on file descriptors has been added to many modern Unix-like systems, as well as numerous C libraries, to be standardized in a future version of POSIX. The at suffix signifies that the function takes an additional first argument supplying a file descriptor from which relative paths are resolved, the forms lacking the at suffix thus becoming equivalent to passing a file descriptor corresponding to the current working directory. The purpose of these new operations is to defend against a certain class of TOCTOU attacks.
openat()faccessat()fchmodat()fchownat()fstatat()futimesat()linkat()mkdirat()mknodat()readlinkat()renameat()symlinkat()unlinkat()mkfifoat()fdopendir()
File descriptors as capabilities
Unix file descriptors behave in many ways as capabilities. They can be passed between processes across Unix domain sockets using the sendmsg() system call. Note, however, that what is actually passed is a reference to an “open file description” that has mutable state (the file offset, and the file status and access flags). This complicates the secure use of file descriptors as capabilities, since when programs share access to the same open file description, they can interfere with each other’s use of it by changing its offset or whether it is blocking or non-blocking, for example.In operating systems that are specifically designed as capability systems, there is very rarely any mutable state associated with a capability itself.
A Unix process’ file descriptor table is an example of a C-list.
如果觉得《Linux网络编程--文件描述符》对你有帮助,请点赞、收藏,并留下你的观点哦!