本文是笔者拜读《UNIX环境高级编程》第3章(文件I/O)的学习笔记。本文的主要内容包括ioctl、/dev/fd,第3章的小结和习题。文中不仅包含书中的知识点,也包括笔者的理解。
ioctl函数
ioctl
函数可处理特殊文件的基础设备参数。 特别是,可以使用ioctl
请求来控制字符特殊文件(例如,终端)的许多操作特性。 参数fd
必须是一个打开的文件描述符。第二个参数是设备相关的请求代码。 第三个参数(图中省略了)是指向内存的无类型指针。成功返回非负值,失败返回-1
.
ioctl
函数一直是I/O操作的杂物箱。不能用本章其他函数表示的I/O
操作(如read
、write
、pread
、pwrite
、lseek
等)通常都能用ioctl
表示,如磁带I/O、终端I/O等。终端I/O是使用ioctl
最多的地方,终端I/O
的ioctl
命令需要头文件<termios.h>
。
每个设备驱动程序可以定义它自己专用的一组ioctl
命令,系统则为不同种类的设备提供通用的ioctl
命令。
/dev/fd
较新的系统都有/dev/fd/
目录,打开文件/dev/fd/n
等效于复制文件描述符n
。大多数系统会忽略open
函数指定的flag
,有些系统要求此时的打开模式必须是/dev/fd/0
(标准输入)初始打开时所使用的打开模式的子集。
fd = open("/dev/fd/0", flag);
等效于
fd = dup(0);
描述符0
和fd
共享同一文件表项。如果描述符0
先前被打开为只读,那么程序也只能对fd
进行只读操作。即使下面的调用是成功的:
fd = open("/dev/fd/0", O_RDWR);
但是在Linux
的实现中/dev/fd
是个例外。它把文件描述符映射成指向底层物理文件的符号链接。例如,当打开/dev/fd/0
时,事实上正在打开与标准输入关联的文件,因此返回的文件描述符与/dev/fd
文件描述符的模式并不相关。
标准输入、标准输出和标准错误关联到的是同一文件。
例(Linux环境):
// devfd.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void GetFlag(int fd) {
int val = fcntl(fd, F_GETFL);
if (val == -1) {
perror("get fileFlag error");
}
switch (val & O_ACCMODE) {
case (O_RDONLY):
printf("read only\n");
break;
case (O_WRONLY):
printf("write only\n");
break;
case (O_RDWR):
printf("read and write\n");
break;
default:
printf("unknown access mode\n");
break;
}
if (val & O_APPEND)