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) 與網絡接口有關的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無線網絡卡會保
總結
- 上一篇: 2020年短视频及电商直播趋势报告
- 下一篇: 2020年中国保险中介市场生态白皮书