ioctl用于向设备发控制和配置命令,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的,称为Out-of-band数据。也就是说,read/write读写的数据是in-band数据,是I/O操作的主体,而ioctl命令传送的是控制信息,其中的数据是辅助的数据。例如,在串口线上收发数据通过read/write操作,而串口的波特率、校验位、停止位通过ioctl设置,A/D转换的结果通过read读取,而A/D转换的精度和工作频率通过ioctl设置。头文件及函数原型:
1 #include <sys/ioctl.h> 2 int ioctl(int d, int request, ...);
d是某个设备的文件描述符。request是ioctl的命令,可变参数取决于request,通常是一个指向变量或结构体的指针。若出错则返回-1,若成功则返回其他值,返回值也是取决于request。
以下程序使用TIOCGWINSZ命令获得终端设备的窗口大小。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/ioctl.h> 5 #include <iostream> 6 using namespace std; 7 8 int main(void) 9 { 10 struct winsize size;//该结构体是在sys/ioctl.h中被内核定义的 11 //isatty(fd);作用是检测fd中的文件描述符是否为tty终端文件,是则返回大于0的数 12 if (isatty(STDOUT_FILENO) == 0) 13 return 1; 14 //获取终端窗口的大小,将获取的值放到size结构体中 15 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)<0) { 16 cout << "ioctl TIOCGWINSZ error" << endl; 17 return 1; 18 } 19 //cout << size.ws_row << size.ws_col << size << endl; 20 printf("%d rows, %d columns ,%d", size.ws_row, size.ws_col,size); 21 return 0; 22 } 23 //在图形界面的终端里多次改变终端窗口的大小并运行该程序,观察结果。
ioctl是对应于不同的驱动的,没有固定的用法,这里举例获取终端的窗口大小。
ioctl不同于fcntl,前者可以获取设备的物理信息,而后者之只获取访问控制属性。
不同的设备文件的ioctl会有不同的操作,对比于下一个例子。
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <stdlib.h> 6 #include <linux/fb.h> 7 #include <sys/ioctl.h> 8 #include <iostream> 9 using namespace std; 10 11 int main(void) 12 { 13 int fd; 14 15 struct fb_var_screeninfo fb_info; 16 17 fd = open("/dev/fb0",O_RDONLY); 18 if(fd < 0) 19 { 20 cout << "open /dev/fb0" << endl; 21 return 1; 22 } 23 24 ioctl(fd, FBIOGET_VSCREENINFO, &fb_info); 25 printf("R = %d, C = %d ",fb_info.xres,fb_info.yres); 26 27 close(fd); 28 29 return 0; 30 }