Linux网络编程--文件描述符
文件描述符
在Unix和Unix-like操作系統中,文件描述符(file descriptor, FD)是一個文件或者像pipe或者network socket等之類的輸入/輸出源的唯一標識。
文件描述符通常是一個非負整數,負數通常代表無值或者錯誤。
文件描述符是POSIX API的一部分。每個除deamons之外的進程都有三個標準的POSIX文件描述符,對應三個標準流:
| 0 | Standard input | STDIN_FILENO | stdin |
| 1 | Standard output | STDOUT_FILENO | stdout |
| 2 | Standard error | STDERR_FILENO | stderr |
概述
在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网络编程--文件描述符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内核编程之Hello_kernel
- 下一篇: 关于linux的进程和线程