fcntl函数,也就是,提供了对文件描述符的各种操作。另一个常见的控制文件描述符的属性和行为的系统调用是,而且比能够执行更多的控制。但是,对于控制文件描述符常见的属性和行为,函数是由POSIX规范指定的首选方法
- ioctl()是底层的系统调用(system call),所以跨平台特性不好。
- 而fcntl则是被封装的函数,各个OS都是支持的。
fcntl()的用途之一是针对一个打开的文件,获取或者修改器访问模式和状态标志(这些值是通过指定open()调用的flag参数来设置的)。要获取这些设置,应将 fcntl()的 cmd 参数设置为F_GETFL:
在上述代码之后,可以以如下代码测试文件是否以同步写方式打开:
SUSv3 规定:针对一个打开的文件,只有通过 open()或后续 fcntl()的 F_SETFL 操作,才能对该文件的状态标志进行设置。然而在如下方面,Linux 实现与标准有所偏离:如果一个程序编译时采用了 5.10 节所提及的打开大文件技术,那么当使用 F_GETFL 命令获取文件状态标志时,标志中将总是包含 O_LARGEFILE 标志。
判定文件的访问模式有一点复杂,这是因为 O_RDONLY(0)、O_WRONLY(1)和 O_RDWR(2)这 3 个常量并不与打开文件状态标志中的单个比特位对应。因此,要判定访问模式,需使用掩码 O_ACCMODE 与 flag 相与,将结果与 3 个常量进行比对:
综上所示,完整代码如下:
测试
使用fcntl()修改文件状态标志,尤其适用于如下场景
- 文件不是由调用程序打开的,所以程序也无法使用open()调用来控制文件的状态标志(比如,文件时3个标准输入输出描述符中的一员,这些描述符在程序启动之前就被打开)
- 文件描述符的获取是通过 open()之外的系统调用
- 比如 pipe()调用,该调用创建一个管道,并返回两个文件描述符分别对应管道的两端。
- 比如 socket()调用,该调用创建一个套接字并返回指向该套接字的文件描述符
为了修改打开文件的状态标志,可以使用 fcntl()的 F_GETFL 命令来获取当前标志的副本,然后修改需要变更的比特位,最后再次调用 fcntl()函数的 F_SETFL 命令来更新此状态标志。
设置文件属性
清除文件属性
设置/清除文件描述符为非阻塞的
O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非阻塞模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会阻塞等待。
它们的差别在于:在读操作时,如果读不到数据,O_NDELAY会使I/O函数马上返回0,但这又衍生出一个问题,因为读取到文件末尾(EOF)时返回的也是0,这样无法区分是哪种情况。因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。
O_NDELAY是在System V的早期版本中引入的,在编码时,还是推荐POSIX规定的O_NONBLOCK,O_NONBLOCK可以在open和fcntl时设置。
- acl_non_blocking.c
- acl_non_blocking.h
fcntl函数支持的常用操作以其参数如表所示:


和这两个信号与其他Linux信号不同,它们必须和某个文件描述符相关联方可使用:
- 当被关联的文件描述符可读或者可写时,系统将触发信号
- 当被关联的文件描述符(必须是一个socket)上有带外数据可读时,系统将触发信号
将信号和文件描述符关联的方法,就是使用函数为目标文件描述符指定宿主进程或者进程组,那么被指定的宿主进程或者进程组将会捕获这两个信号
使用时,还需要利用设置其标志(异步IO标志)
:
- 返回fd对应的文件状态标志

版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/9246.html