fcntl(file control) 用于对已打开的文件描述符进行各种操作。
/*
* fd: 文件描述符
* cmd: 执行的操作
* arg: 类型和意义取决于cmd
*/
int fcntl(int fd, int cmd, ... /* arg */ );
获取/设置socket文件描述符状态
获取/设置socket文件描述符的读写模式。
cmd 值 |
描述 |
arg 参数 |
作用及用法 |
F_GETFL |
获取文件描述符状态标志。 |
忽略 |
获取当前 socket 的状态标志,例如是否为非阻塞模式。
int flags = fcntl(sockfd, F_GETFL); |
F_SETFL |
设置文件描述符状态标志。 |
int |
用于设置 socket 为非阻塞模式。
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); |
通常在使用 F_SETFL 时,先用 F_GETFL 获取当前标志,然后通过位运算来添加或移除你需要的标志,最后再用 F_SETFL 设置回去。
| 标志 |
描述 |
用途 |
O_NONBLOCK |
非阻塞模式 |
最常用。 当 I/O 操作(如 read, write, accept, connect)在数据未就绪时,函数会立即返回 -1,并设置 errno 为 EAGAIN 或 EWOULDBLOCK,而不是阻塞等待。这在非阻塞 I/O 和 I/O 多路复用中至关重要。 |
O_ASYNC |
信号驱动 I/O |
启用此标志后,当 I/O 事件(如数据可读)发生时,内核会向拥有该文件描述符的进程发送一个 SIGIO 信号。这需要配合 fcntl 的 F_SETOWN 命令来指定接收信号的进程。 |
获取/设置socket文件描述符
获取/设置socket文件描述符的自身属性。
cmd 值 |
描述 |
arg 参数 |
作用及用法 |
F_GETFD |
获取文件描述符标志。 |
忽略 |
返回 FD_CLOEXEC 标志的值,表示是否在 exec 时关闭。
int flags = fcntl(sockfd, F_GETFD); |
F_SETFD |
设置文件描述符标志。 |
int |
用于设置 FD_CLOEXEC 标志。防止子进程意外继承父进程的 socket。
fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC); |
获取/设置socket文件描述符拥有者
cmd 值 |
描述 |
arg 参数 |
作用及用法 |
F_GETOWN |
获取socket的I/O事件通知拥有者(进程 ID 或进程组 ID)。 |
忽略 |
返回拥有者的 ID。
int owner = fcntl(sockfd, F_GETOWN); |
F_SETOWN |
设置 socket 的 I/O 事件通知拥有者。 |
int |
设置拥有者的 ID。这个 ID 可以是一个进程 ID(正数)或一个进程组 ID(负数)。当 socket 上设置了 O_ASYNC 标志时,内核会向此 ID 发送 SIGIO 信号。
fcntl(sockfd, F_SETOWN, getpid()); |
复制socket文件描述符
cmd 值 |
描述 |
arg 参数 |
作用及用法 |
F_DUPFD |
复制文件描述符。 |
int |
复制 sockfd,返回一个大于等于 arg 的新文件描述符。新旧描述符共享文件状态和偏移量。 |
F_DUPFD_CLOEXEC |
复制文件描述符并设置 CLOEXEC 标志。 |
int |
和 F_DUPFD 类似,但新描述符会自动设置 FD_CLOEXEC 标志,确保在子进程执行 exec 时自动关闭。这是比 F_DUPFD 更安全的选项。 |