锁定老帖子 主题:ioctl函数详细说明
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (6)
|
|||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||||||||||||||
发表时间:2009-01-04
最后修改:2009-01-04
ioctl 函数
本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h> int ioctl( int fd, int request, .../* void *arg */ ); 返回0 :成功 -1 :出错
第三个参数总是一个指针,但指针的类型依赖于request 参数。 我们可以把和网络相关的请求划分为6 类: 套接口操作 文件操作 接口操作 ARP 高速缓存操作 路由表操作 流系统 下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
套接口操作: 明确用于套接口操作的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 结构。
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无线网络卡会保
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||
浏览 45342 次