最复杂的函数----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 成员也被更新,以反映存放在缓冲区中的信息量。

接 口操作:

SIOCGIFCONF 请求为每个已配置的接口返回其名字以及一个套接口地址结构。我们接着可以发出多个接 口类其他请求以设置或获取每个接口的其他特征。这些请求的获取( get )版本( SIOCGxxx ) 通常由 netstat 程序发出,设置( set ) 版本( SIGOCSxxx )通常由 ifconfig 程 序发出。任何用户都可以获取接口信息,设置接口信息却要求有超级用户权限。

 

这些请求汲取或返回一个一个 ifreq 结构中的信息,而这个结构的地址则作为 ioctl 调 用的第三个参数制定。接口总是以其名标志,在 ifreq 结构的 ifr_name 成 员中指定,如 le0 , lo0 , ppp0 等。

这些请求中有许多使用套接口地址结构在应用进程和内核之间指定或返回具体接口的 IP 地 址或地址掩码。对于 IPV4 ,这个地址或掩码放在一个网际套接口地址结构的 sin_addr 成 员中;对于 IPV6 ,它是一个 IPV6 套接 口地址结构的 sin6_addr 成员。

 

SIOCGIFADDR :   在 ifr_addr 成 员中返回单播地址。

SIOCSIFADDR :用 ifr_addr 成员设 置接口地址,这个接口的初始化函数也被调用。

 

SIOCGIFFLAGS : 在 ifr_flags 成员中返回接口标志。这些接口标志的名字格式为 IFF_XXX, 在 <net/if.h> 头 文件中定义。举例来说,这些标志指示接口是否处于 UP 即在工状态 (IFF_UP), 是 否为一个点到点接口( IFF_POINTOPOINT ) , 是 否支持广播( IFF_BROADCAST ) , 等 等。

SIOCSIFFLAGS : 用 ifr_flags 成员设置接口标志。

SIOCGIFDSTADDR : 在 ifr_dstaddr 成员中返回点到点地址。

SIOCSIFDSTADDR:  在 ifr_dstaddr 成员中设置点到点地址

SIOCGIFBRDADDR:  在 ifr_broadaddr 成员中返回广播地址。应 用进程必须首先获取接口标志,然后发出正确的请求;对于广播接口为 SIOCGIFBRDADDR , 对于点到点接口为 SIOCGIFDSTADDR

SIOCSIFBRDADDR : 用 ifr_broadaddr 成员设置广播地址。

SIOCGIFNETMASK : 在 ifr_addr 成员中返回子网掩码。

SIOCSIFNETMASK : 在 ifr_addr 成员中设置子网掩码。

SIOCGIFMETRIC : 用 ifr_metric 成员返回接口测度。接口测度由内核为每个接口维护,不过使用他的是路由守护 进程 routed 。接口测度被 routed 加 到跳数上。

SIOCSIFMETRIC : 用 ifr_metric 成员设置接口的路由测度。

 

 

 

ARP 高 速缓存操作

ARP 告 诉缓存也通过 ioctl 函数操纵。使用路由域套接口的系统往往改用路由套接口访问

ARP 高 速缓存。这些请求使用如下的 arpreq 结构,定义在 <net/if_arp.h>

 

struct arpreq {

    struct sockaddr      arp_pa;

    struct sockaddr      arp_ha;

     int                  arp_flags;

};

 

#define ATF_INUSE      0x01   //entry in use

#define ATF_COM         0x02   //completed entry ( hardware addr valid )

#define ATF_PERM       0x04   // permanent entry

#define ATF_PUBL 0x08   // published entry (respond for other host )

 

Ioctl 的 第三个必须指向某个 arpreq 结构,操纵 ARP 高 速缓存的 ioctl 请求有以下三个:

 

SIOCSARP:           把一个新的表项加入 ARP 告诉缓存中区,或者修改其中 已经存在的一个表项,其中 arp_pa 是一个含有 IP 地 址的网际套接口地址结构, arp_ha 则是一个通用套接口地址结构,他的 sa_family 值 为 AF_unspec,sa_data 中含有硬件地址(例如 6 直 接的以太网地址)。 ATF_PERM 和 ATF_PUBL 这 两个标志也可以由应用进程指定。另外两个标志( ATF_INUSE 和 ATF_COM ) 则由内核设置。

SIOCDARP :         从 ARP 告诉缓存中删除一个表项。调用者指定要删除表 项的网际地址。

SIOCGARP :         从 ARP 高速缓存中获取一个表项。调用者指定网际地 址,相应的硬件地址(例外以太网地址)随标志一起返回。

 

只有超级用户才能增加或删除表项。 这三个请求通常由 arp 程序发出。

注意 ioctl 没 有办法列出 ARP 高速缓存中的所有表项。当指定 -a 标 志执行 arp 命令时,大多

数版本的 arp 程 序通过读取内核的内存 ( /dev/kmem ) 获得 ARP 高 速缓存的当前内容。

 

路由 表操作  

有些系统提供 2 个 用于操纵路由表的 ioctl 请求。这 2 个请 求要求 ioctl 的第三个参数是指向

某个 rtentry 结 构的一个指针,该结构定义在 <net/route.h> 头文件中。这些请求通常由 route

程序发出。只有超级用户才能发出这 些请求。

SIOCADDRT : 往路由表中增加一个表项

SIOCDELRT : 从路由表中删除一个表项

Ioctl 没 有办法列出路由表中的所有表项。这个操作通常由 netstat 程序在指定 -r 标 志自行四

完成。 netstat 程 序通过读取内核的内存   ( /dev/kmem ) 获得整个路由表。用 sysctl 同样可

以做到。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值