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,并设置 errnoEAGAINEWOULDBLOCK,而不是阻塞等待。这在非阻塞 I/O 和 I/O 多路复用中至关重要。
O_ASYNC 信号驱动 I/O 启用此标志后,当 I/O 事件(如数据可读)发生时,内核会向拥有该文件描述符的进程发送一个 SIGIO 信号。这需要配合 fcntlF_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 更安全的选项。