ioctl函数操作
第十六章 ioctl操作
传统上ioctl函数是用于那些普遍使用,但不适合归入其他类别的任何特性的系统接口。Posix去掉了ioctl,它通过
创建特殊的其功能已被Posix标准化的包裹函数来代替ioctl。这一章介绍和网络编程有关的ioctl操作。
1. ioctl函数
int ioctl(int d, int request, ...);
和网络有关的ioctl请求有6类:
套接口操作
文件操作
接口操作
ARP高速缓存操作
路由表操作
流系统
2. 套接口操作
| 类别 | 请求 | 描述 | 数据类型 |
| 套接口 | SIOCATMASK | 在带外标志上吗 | int |
| SIOCSPGRP | 设置套接口的进程ID和进程组ID | int | |
| SIOCGPGPR | 获取套接口的进程ID和进程组ID | int |
SIOCATMASK: 如果套接口的读指针在带外标志上,则通过第三个参数指向的整数返回一个非零值,否则返回零。
3. 文件操作
| 类别 | 请求 | 描述 | 数据类型 |
| 文件操作 | FIONBIO | 设置/清除非阻塞标志 | int |
| FIOASYNC | 设置/清除异步I/O标志 | int | |
| FIONREAD | 获取接收缓冲区中数据的字节数 | int | |
| FIOSETOWN | 设置文件的进程ID或进程组ID | int | |
| FIOGETOWN | 获取文件的进程ID或进程组ID | int |
FIONBIO: 这个请求和用fcntl的F_SETFL命令设置和清除O_NONBLOCK标志效果相同。
4. 接口配置
| 类别 | 请求 | 描述 | 数据类型 |
| 接口 | SIOCGIFCONF | 获取所有接口的列表 | struct ifconf |
| SIOCSIFADDR | 设置接口地址 | struct ifreq | |
| SIOCGIFADDR | 获取接口地址 | struct ifreq | |
| SIOCSIFFLAGS | 设置接口标志 | struct ifreq | |
| SIOCGIFFLAGS | 获取接口标志 | struct ifreq | |
| SIOCSIFDSTADDR | 设置点对点地址 | struct ifreq | |
| SIOCGIFDSTADDR | 获取点对点地址 | struct ifreq | |
| SIOCGIFBRDADDR | 获取广播地址 | struct ifreq | |
| SIOCSIFBRDADDR | 设置广播地址 | struct ifreq | |
| SIOCGIFNETMASK | 获取子网掩码 | struct ifreq | |
| SIOCSIFNETMASK | 设置子网掩码 | struct ifreq | |
| SIOCGIFMETRIC | 获取接口的测度(metric) | struct ifreq | |
| SIOCSIFMETRIC | 设置接口的测度(metric) | struct ifreq | |
| SIOCxxx |
5. ARP
| 类别 | 请求 | 描述 | 数据类型 |
| ARP | SIOCSARP | 创建/修改ARP项 | struct arpreq |
| SIOCGARP | 获取ARP项 | struct arpreq | |
| SIOCDARP | 删除ARP项 | struct arpreq |
6. 路由
| 类别 | 请求 | 描述 | 数据类型 |
| 路由 | SIOCADDRT | 增加路径 | struct rtentry |
| SIOCDELRT | 删除路径 | struct rtentry |
具体到套接字方面的应用可以看下面的讲解
NAME
netdevice - 底层访问 Linux 网络设备.总览 (SYNOPSIS)
#include <sys/ioctl.h>#include <net/if.h>
描述 (DESCRIPTION)
本手册 描述 用于 配置 网络设备 的 套接字(socket) 接口.Linux 支持 一些 配置 网络设备 的 标准 ioctl. 他们 用于 任意的 套接字 描述符, 而 无须 了解 其 类型 或 系列. 他们 传递 一个 ifreq结构:
struct ifreq
{
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char * ifr_data;
};
}
struct ifconf
{
int ifc_len; /* size of buffer */
union {
char * ifc_buf; /* buffer address */
struct ifreq *ifc_req; /* array of structures */
};
};
一般说来, ioctl 通过 把 ifr_name 设置为 接口 的 名字 来 指定 将要 操作 的 设备. 结构的 其他成员 可以 分享 内存.
IOCTLS
如果 某个 ioctl 标记为 特权操作, 那么 操作时 需要 有效uid 为 0, 或者 拥有 CAP_NET_ADMIN 能力. 否则 将 返回 EPERM .- SIOCGIFNAME
- 给定 ifr_ifindex, 返回 ifr_name 中 的 接口名字. 这是 唯一 返回 ifr_name 内容 的 ioctl.
- SIOCGIFINDEX
- 把 接口 的 索引 存入 ifr_ifindex.
- SIOCGIFFLAGS, SIOCSIFFLAGS
- 读取 或 设置 设备的 活动标志字. ifr_flags 包含 下列值 的 屏蔽位:
设备标志 IFF_UP 接口正在运行. IFF_BROADCAST 有效的广播地址集. IFF_DEBUG 内部调试标志. IFF_LOOPBACK 这是自环接口. IFF_POINTOPOINT 这是点到点的链路接口. IFF_RUNNING 资源已分配. IFF_NOARP 无arp协议, 没有设置第二层目的地址. IFF_PROMISC 接口为杂凑(promiscuous)模式. IFF_NOTRAILERS 避免使用trailer . IFF_ALLMULTI 接收所有组播(multicast)报文. IFF_MASTER 主负载平衡群(bundle). IFF_SLAVE 从负载平衡群(bundle). IFF_MULTICAST 支持组播(multicast). IFF_PORTSEL 可以通过ifmap选择介质(media)类型. IFF_AUTOMEDIA 自动选择介质. IFF_DYNAMIC 接口关闭时丢弃地址. 设置 活动标志字 是 特权操作, 但是 任何进程 都可以 读取 标志字.
- SIOCGIFMETRIC, SIOCSIFMETRIC
- 使用 ifr_metric 读取 或 设置 设备的 metric 值. 该功能 目前 还没有 实现. 读取操作 使 ifr_metric 置 0, 而 设置操作 则 返回 EOPNOTSUPP.
- SIOCGIFMTU, SIOCSIFMTU
- 使用 ifr_mtu 读取 或 设置 设备的 MTU(最大传输单元). 设置 MTU 是 特权操作. 过小的 MTU 可能 导致 内核 崩溃.
- SIOCGIFHWADDR, SIOCSIFHWADDR
- 使用 ifr_hwaddr 读取 或 设置 设备的 硬件地址. 设置 硬件地址 是 特权操作.
- SIOCSIFHWBROADCAST
- 使用 ifr_hwaddr 读取 或 设置 设备的 硬件广播地址. 这是个 特权操作.
- SIOCGIFMAP, SIOCSIFMAP
- 使用 ifr_map 读取 或 设置 接口的 硬件参数. 设置 这个参数 是 特权操作.
struct ifmap { unsigned long mem_start; unsigned long mem_end; unsigned short base_addr; unsigned char irq; unsigned char dma; unsigned char port; };对 ifmap 结构 的 解释 取决于 设备驱动程序 和 体系结构.
- SIOCADDMULTI, SIOCDELMULTI
- 使用 ifr_hwaddr 在 设备的 链路层 组播过滤器 (multicase filter) 中 添加 或 删除 地址. 这些是 特权操作. 参看 packet(7).
- SIOCGIFTXQLEN, SIOCSIFTXQLEN
- 使用 ifr_qlen 读取 或 设置 设备的 传输队列长度. 设置 传输队列长度 是 特权操作.
- SIOCSIFNAME
- 把 ifr_ifindex 中 指定的 接口名字 改成 ifr_newname. 这是个 特权操作.
- SIOCGIFCONF
- 返回 接口地址(传输层) 列表. 出于 兼容性, 目前 只代表 AF_INET 地址. 用户 传送 一个 ifconf 结构 作为 ioctl 的 参数. 其中ifc_req 包含 一个 指针 指向 ifreq 结构数组, 他的 长度 以字节 为单位 存放在 ifc_len 中. 内核 用 所有 当前的 L3(第三层?) 接口地址 填充 ifreqs, 这些 接口 正在 运行: ifr_name 存放 接口名字 (eth0:1等), ifr_addr 存放 地址. 内核 在 ifc_len 中 返回 实际长度; 如果 他 等于 初始长度, 表示 溢出了, 用户 应该 换一个 大些的 缓冲区 重试 一下. 没有 发生 错误时 ioctl 返回 0, 否则 返回 -1, 溢出 不算 错误.
大多数 协议 使用 自己的 ioctl 配置 协议 特定的 接口 操作. 具体 情况参看 协议的 帮助手册. 要配置 IP 地址 可以 参看 ip(7).
另外, 某些 设备 有 专用的 ioctl, 这里 不做 叙述.

浙公网安备 33010602011771号