这一节继续讲解系统IO函数
(1) dup
头文件:#include <unistd.h>
定义函数:int dup (int oldfd);
说明:dup()用来复制参数oldfd所指向的文件描述符,此时返回的新的文件描述符和参数oldfd所指的是同一个文件,共享所有的锁定、读写位置和各项权限或旗标。例如,当利用lseek()对某个文件描述符作用时,另一个文件描述符的读写位置也会随着改变。
(2) dup2
头文件:#include <unistd.h>
定义函数:int dup2(int odlfd, int newfd);
说明:dup2()用来复制参数oldfd所指向的文件描述符,并将它拷贝到参数newfd后一块返回。若参数newfd为一已打开的文件描述符,则newfd所指的文件会先被关闭,dup2()所复制的文件描述符,与原来的文件描述符共享各种文件状态。
两者的区别是dup()只能生成一个未打开的最新的文件描述符,而dup2()可以随意重定向。
(2) fcntl
定义函数:int fcntl(int fd, int cmd, … /* arg */ );
说明:fcntl其实就是对打开的文件描述符进行一系列的控制操作。每一个打开的文件都有很多属性,比如文件描述符的标志(目前只有FD_CLOEXEC一个标志)、文件的状态(O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)。
fcntl的主要功能:
- 复制文件描述符,cmd:F_DUPFD、F_DUPFD_CLOEXEC
- 文件描述符标志位,cmd:F_GETFD、F_SETFD
- 文件状态标志,cmd:F_GETFL、F_SETFL
- 文件建议锁,cmd:F_SETLK, F_SETLKW, and F_GETLK
flag_val |= O_NONBLOCK; //追加文件属性
fcntl(fd, F_SETFL, flag_val); //设置文件属性
(3) ioctl
定义函数:int ioctl(int d, unsigned long request, …);
说明:ioctl是对设备(文件)的控制操作。我们已经提过了对一些文件(设备)的通用操作,但是每一个设备肯定有一些不同于其他设备的功能或者属性。比如网络接口设备有IP、mask等属性或者终端设备有波特率等。
那么对设备的不同属性我们提供了一个“收纳盒”ioctl,因为每一个设备的特性都是不同的,所以不可能有一个统一的命令,而我们也不可能在kernel提供ioctl的具体实现,所以是由每个设备的驱动程序提供设备支持的ioctl功能命令集合。
在fcntl的man手册中列出了支持的所有cmd命令,但是在ioctl的man手册中没有列出支持的命令,这是因为ioctl是每一个设备自身的实现来支持的。系统本身对一些常见的设备会提供一些ioctl支持,定义在系统头文件中。除了这些常见的设备以外,其他的设备的ioctl的支持都需要自己在驱动中编写。