ioctl
函数
本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h>
int
ioctl
( int fd, int request, .../* void *arg */ );
返回0 :成功 -1 :出错
第三个参数总是一个指针,但指针的类型依赖于request 参数。
我们可以把和网络相关的请求划分为6 类:
套接口操作
文件操作
接口操作
ARP
高速缓存操作
路由表操作
流系统
下表列出了网络相关
ioctl
请求的request 参数以及arg 地址必须指向的数据类型:
类别
|
Request
|
说明
|
数据类型
|
套
接
口
|
SIOCATMARK
SIOCSPGRP
SIOCGPGRP
|
是否位于带外标记
设置套接口的进程ID 或进程组ID
获取套接口的进程ID 或进程组ID
|
int
int
int
|
文
件
|
FIONBIN
FIOASYNC
FIONREAD
FIOSETOWN
FIOGETOWN
|
设置/ 清除非阻塞I/O 标志
设置/ 清除信号驱动异步I/O 标志
获取接收缓存区中的字节数
设置文件的进程ID 或进程组ID
获取文件的进程ID 或进程组ID
|
int
int
int
int
int
|
接
口
|
SIOCGIFCONF
SIOCSIFADDR
SIOCGIFADDR
SIOCSIFFLAGS
SIOCGIFFLAGS
SIOCSIFDSTADDR
SIOCGIFDSTADDR
SIOCGIFBRDADDR
SIOCSIFBRDADDR
SIOCGIFNETMASK
SIOCSIFNETMASK
SIOCGIFMETRIC
SIOCSIFMETRIC
SIOCGIFMTU
SIOCxxx
|
获取所有接口的清单
设置接口地址
获取接口地址
设置接口标志
获取接口标志
设置点到点地址
获取点到点地址
获取广播地址
设置广播地址
获取子网掩码
设置子网掩码
获取接口的测度
设置接口的测度
获取接口MTU
(还有很多取决于系统的实现)
|
struct ifconf
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
|
ARP
|
SIOCSARP
SIOCGARP
SIOCDARP
|
创建/ 修改ARP 表项
获取ARP 表项
删除ARP 表项
|
struct arpreq
struct arpreq
struct arpreq
|
路
由
|
SIOCADDRT
SIOCDELRT
|
增加路径
删除路径
|
struct rtentry
struct rtentry
|
流
|
I_xxx
|
|
|
套接口操作:
明确用于套接口操作的
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 )
• 改变路由表 ( 例如 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
无线网络卡会保