ioctl 函数
本函数影响由fd 参数引⽤的⼀个打开的⽂件。
#include int ioctl( int fd, int request, .../* void *arg */ );返回0 :成功 -1 :出错 第三个参数总是⼀个指针,但指针的类型依赖于request 参数。我们可以把和⽹络相关的请求划分为6 类:套接⼝操作⽂件操作接⼝操作 ARP ⾼速缓存操作路由表操作流系统 下表列出了⽹络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型: 类别Request套SIOCATMARK接⼝ ⽂ 件 接⼝ SIOCSPGRPSIOCGPGRPFIONBINFIOASYNCFIONREADFIOSETOWNFIOGETOWN SIOCGIFCONFSIOCSIFADDRSIOCGIFADDRSIOCSIFFLAGSSIOCGIFFLAGS 说明 是否位于带外标记 设置套接⼝的进程ID 或进程组ID获取套接⼝的进程ID 或进程组ID设置/ 清除⾮阻塞I/O 标志设置/ 清除信号驱动异步I/O 标志获取接收缓存区中的字节数设置⽂件的进程ID 或进程组ID获取⽂件的进程ID 或进程组ID 数据类型intintintintintintintintstruct ifconfstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreq 获取所有接⼝的清单设置接⼝地址获取接⼝地址设置接⼝标志获取接⼝标志 SIOCSIFDSTADDR设置点到点地址SIOCGIFDSTADDR获取点到点地址SIOCGIFBRDADDR获取⼴播地址SIOCSIFBRDADDR设置⼴播地址SIOCGIFNETMASK获取⼦⽹掩码 ARP路由流 SIOCGIFNETMASK获取⼦⽹掩码SIOCSIFNETMASK设置⼦⽹掩码SIOCGIFMETRICSIOCSIFMETRICSIOCGIFMTUSIOCxxx 获取接⼝的测度设置接⼝的测度获取接⼝MTU (还有很多取决于系统的实现) struct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreq SIOCSARPSIOCGARPSIOCDARPSIOCADDRTSIOCDELRTI_xxx 创建/ 修改ARP 表项获取ARP 表项删除ARP 表项增加路径删除路径 struct arpreqstruct arpreqstruct arpreqstruct rtentrystruct rtentry 套接⼝操作: 明确⽤于套接⼝操作的ioctl 请求有三个, 它们都要求ioctl 的第三个参数是指向某个整数的⼀个指针。 SIOCATMARK: 如果本套接⼝的的度指针当前位于带外标记,那就通过由第三个参数指向的整数返回⼀个⾮0 值;否则返回⼀个0 值。POSIX 以函数sockatmark 替换本请求。 SIOCGPGRP : 通过第三个参数指向的整数返回本套接⼝的进程ID 或进程组ID ,该ID 指定针对本套接⼝的SIGIO 或SIGURG 信号的接收进程。本请求和fcntl 的F_GETOWN 命令等效,POSIX 标准化的是fcntl 函数。 SIOCSPGRP : 把本套接⼝的进程ID 或者进程组ID 设置成第三个参数指向的整数,该ID 指定针对本套接⼝的SIGIO 或SIGURG 信号的接收进程,本请求和fcntl 的F_SETOWN 命令等效,POSIX 标准化的是fcntl 操作。 ⽂件操作: 以下5 个请求都要求ioctl 的第三个参数指向⼀个整数。 FIONBIO : 根据ioctl 的第三个参数指向⼀个0 或⾮0 值分别清除或设置本套接⼝的⾮阻塞标志。本请求和O_NONBLOCK ⽂件状态标志等效,⽽该标志通过fcntl 的F_SETFL 命令清除或设置。 FIOASYNC : 根据iocl 的第三个参数指向⼀个0 值或⾮0 值分别清除或设置针对本套接⼝的信号驱动异步I/O 标志,它决定是否收取针对本套接⼝的异步I/O 信号(SIGIO )。本请求和O_ASYNC ⽂件状态标志等效,⽽该标志可以通过fcntl 的F_SETFL 命令清除或设置。 FIONREAD : 通过由ioctl 的第三个参数指向的整数返回当前在本套接⼝接收缓冲区中的字节数。本特性同样适⽤于⽂件,管道和终端。 FIOSETOWN : 对于套接⼝和SIOCSPGRP 等效。FIOGETOWN : 对于套接⼝和SIOCGPGRP 等效。 接⼝配置: 得到系统中所有接⼝由SIOCGIFCONF 请求完成,该请求使⽤ifconf 结构,ifconf ⼜使⽤ifreq结构,如下所⽰: Struct ifconf{ int ifc_len; // 缓冲区的⼤⼩ union{ caddr_t ifcu_buf; // input from user->kernel struct ifreq *ifcu_req; // return of structures returned }ifc_ifcu;}; #define ifc_buf ifc_ifcu.ifcu_buf //buffer address #define ifc_req ifc_ifcu.ifcu_req //array of structures returned #define IFNAMSIZ 16 struct ifreq{ char ifr_name[IFNAMSIZ]; // interface name, e.g., “le0” union{ struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; short ifru_flags; int ifru_metric; caddr_t ifru_data; }ifr_ifru;}; #define ifr_addr ifr_ifru.ifru_addr // address #define ifr_dstaddr ifr_ifru.ifru_dstaddr // otner end of p-to-p link#define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address#define ifr_flags ifr_ifru.ifru_flags // flags#define ifr_metric ifr_ifru.ifru_metric // metric #define ifr_data ifr_ifru.ifru_data // for use by interface 再调⽤ioctl 前我们必须先分撇⼀个缓冲区和⼀个ifconf 结构,然后才初始化后者。如下图展⽰了⼀个ifconf 结构的初始化结构,其中缓冲区的⼤⼩为1024 ,ioctl 的第三个参数指向这样⼀个ifconf 结构。ifc_len Ifc_buf 1024 ---------------------> 缓存 假设内核返回2 个ifreq 结构,ioctl 返回时通过同⼀个ifconf 结构缓冲区填⼊了那2 个ifreq 结构,ifconf 结构的ifc_len 成员也被更新,以反映存放在缓冲区中的信息量 ⼀般来讲ioctl在⽤户程序中的调⽤是:ioctl(int fd,int command, (char*)argstruct) ioctl调⽤与⽹络编程有关(本⽂只讨论这⼀点),⽂件描述符fd实际上是由socket()系统调⽤返回的。参数command的取值由/usr/include/linux/sockios.h 所规定。这些command的由于功能的不同,可分为以下⼏个⼩类:• 改变路由表 (例如 SIOCADDRT, SIOCDELRT), • 读/更新 ARP/RARP 缓存(如:SIOCDARP, SIOCSRARP), • ⼀般的与⽹络接⼝有关的(例如 SIOCGIFNAME, SIOCSIFADDR 等等) 在 Gooodies⽬录下有很多样例程序展⽰了如何使⽤ioctl。当你看这些程序时,注意参数argstruct是与参数command相关的。例如,与 路由表相关的ioctl使⽤rtentry这种结构,rtentry定义在/usr/include/linux/route.h(参见例⼦ adddefault.c)。与ARP有关的ioctl调⽤使⽤arpreq结构,arpreq定义在/usr/include/linux /if_arp.h(参见例⼦arpread.c) 与⽹络接⼝有关的ioctl调 ⽤使⽤的command参数通常看起来像SIOCxIFyyyy的形式,这⾥x要 么是S(设定set,写write),要么是G(得到get,读read)。在getifinfo.c程序中就使⽤了这种形式的command参数来读 IP地址,硬件地址,⼴播地址和得到与⽹络接⼝有关的⼀些标志(flag)。在这些ioctl调⽤中,第三个参数是ifreq结构,它在/usr /include/linux/if.h中定义。在某些情况下, ioctrl调⽤可能会使⽤到在sockios.h之外的新的定义,例如,WaveLAN⽆线⽹络卡会保 因篇幅问题不能全部显示,请点此查看更多更全内容