本函數影響由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 成員也被更新,以反映存放在緩衝區中的信息量
• 改變路由表 (例如 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)