Linux中的高级IO函数(三)fcntl

Linux提供了很多高级的I/O函数。它们并不像Linux基础I/O函数(比如open和read)那么常用(编写内核模块时一般要实现这些I/O函数),但在特定的条件下却表现出优秀的性能。这些函数大致分为三类:

用于创建文件描述符的函数,包括pipe、socketpair、dup/dup2函数。

用于读写数据的函数,包括readv/writev、sendfile、mmap/munmap、splice和tee函数。

用于控制I/O行为和属性的函数,包括fcntl函数。

本节接着介绍第三类

一、fcntl函数

fcntl函数全称是 file control 。该函数提供了对文件描述符的各种控制操作。另外一个常见的控制文件描述符属性和行为的系统调用是ioctl,而且ioctlfcntl能够执行更多的控制。但是,对于控制文件描述符常用的属性和行为,fcntl函数是由POSIX规范指定的首选方法。

c 复制代码
#include <fcntl.h>

int fcntl(int fd, int cmd,  ...);
  • fd参数是被操作的文件描述符

  • cmd参数指定执行何种类型的操作

下面是一些常见的操作

cmd 含义 第三个参数类型 成功时返回值
F_DUPFD 复制文件描述符 int 复制的新文件描述符
F_GETFD 获取文件描述符标志 文件描述符标志位(整数)
F_SETFD 设置文件描述符标志 int 0(成功)或 -1(失败)
F_GETFL 获取文件状态标志 文件状态标志位(整数)
F_SETFL 设置文件状态标志 int 0(成功)或 -1(失败)
F_GETLK 获取记录锁 struct flock * 0(无冲突)或 -1(失败)
F_SETLK 设置记录锁 const struct flock * 0(成功)或 -1(失败)
F_SETLKW 设置记录锁(阻塞版本) const struct flock * 0(成功)或 -1(失败)
F_GETOWN 获取异步I/O所有权 所有权的进程ID(整数)
F_SETOWN 设置异步I/O所有权 pid_t 0(成功)或 -1(失败)
F_GETLK64 获取记录锁(64位版本) struct flock64 * 0(无冲突)或 -1(失败)
F_SETLK64 设置记录锁(64位版本) const struct flock64 * 0(成功)或 -1(失败)
F_SETLKW64 设置记录锁(阻塞版本,64位版本) const struct flock64 * 0(成功)或 -1(失败)
F_GETSIG 获取信号 信号值(整数)
F_SETSIG 设置信号 int 0(成功)或 -1(失败)
F_GETLEASE 获取文件租约状态 租约状态(整数)
F_SETLEASE 设置文件租约 int 0(成功)或 -1(失败)
F_NOTIFY 监视文件状态变化 int 0(成功)或 -1(失败)
F_GETPIPE_SZ 获取管道容量 管道容量(整数)
F_SETPIPE_SZ 设置管道容量 int 0(成功)或 -1(失败)
F_GET_SEALS 获取文件封印状态 文件封印状态(整数)
F_ADD_SEALS 添加文件封印 unsigned int 0(成功)或 -1(失败)
F_GET_RW_HINT 获取读写优化提示 读写优化提示(整数)
F_SET_RW_HINT 设置读写优化提示 unsigned int 0(成功)或 -1(失败)
F_GET_FILE_RW_HINT 获取文件读写优化提示 读写优化提示(整数)
F_SET_FILE_RW_HINT 设置文件读写优化提示 unsigned int 0(成功)或 -1(失败)
F_GETLKPID 获取记录锁并返回占有者的进程ID struct flock * 占有者的进程ID(整数)或 -1(失败)
F_OFD_GETLK 获取OFD记录锁 struct flock * 0(无冲突)或 -1(失败)
F_OFD_SETLK 设置OFD记录锁 const struct flock * 0(成功)或 -1(失败)
F_OFD_SETLKW 设置OFD记录锁(阻塞版本) const struct flock * 0(成功)或 -1(失败)

在常见的编程中,fcntl函数通常用来将一个文件描述符设置为非阻塞的。

c 复制代码
int setnonblocking(int fd) {
	/* 获取文件描述符旧的状态标志 */
    int old_option=fcntl(fd,F_GETFL);
    /* 设置非阻塞标志 */
    int new_option=old_option|O_NONBLOCK;
    /* 写入设置 */
    fcntl(fd,F_SETFL,new_option);
    /* 返回文件描述符旧的状态标志,以便日后恢复该状态标志 */
    return old_option;
}

此外,SIGIOSIGURG这两个信号与其他Linux信号不同,它们必须与某个文件描述符相关联方可使用:当被关联的文件描述符可读或可写时,系统将触发SIGIO信号;当被关联的文件描述符(而且必须是一个socket)上有带外数据可读时,系统将触发SIGURG信号。将信号和文件描述符关联的方法,就是使用fcntl函数为目标文件描述符指定宿主进程或进程组,那么被指定的宿主进程或进程组将捕获这两个信号。

相关推荐
caijingshiye22 分钟前
九科信息企业自动化智能体:打破知行割裂,让AI真正动手干活
运维·人工智能·自动化
Funny_AI_LAB1 小时前
李飞飞联合杨立昆发表最新论文:超感知AI模型从视频中“看懂”并“预见”三维世界
人工智能·算法·语言模型·音视频
HIT_Weston2 小时前
26、【Ubuntu】【远程开发】内网穿透:密钥算法介绍(二)
linux·运维·ubuntu
zl_dfq4 小时前
Linux第一个小程序 之 【进度条】
linux
wdfk_prog4 小时前
[Linux]学习笔记系列 -- [kernel]kthread
linux·笔记·学习
RTC老炮4 小时前
webrtc降噪-PriorSignalModelEstimator类源码分析与算法原理
算法·webrtc
大地的一角4 小时前
(Linux)ELF格式与库的链接原理
linux·运维·服务器
z202305084 小时前
Linux之中断子系统-内核中断注册源码分析(4)
linux·运维·服务器
深思慎考5 小时前
微服务即时通讯系统(服务端)——用户子服务实现逻辑全解析(4)
linux·c++·微服务·云原生·架构·通讯系统·大学生项目
极小狐6 小时前
比 Cursor 更丝滑的 AI DevOps 编程智能体 - CodeRider-Kilo 正式发布!
运维·人工智能·devops