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更安全的选项。 |