一般的說,,使用者空間的IOCTL系統調用如下所示: ioctl(int fd, int command, (char *) argstruct)因為這個調用擁有與網絡相關的代碼,是以檔案描述符号fd就是socket()系統調用所傳回的,而command參數可以是/usr/include/linux/sockios.h頭檔案中的任何一個,這些個指令根據它可以解決的問題所涉及的方面被分為多種的類型.
比如:
改變路由表(SIOCADDRT, SIOCDELRT)
讀取或更新ARP/RARP緩存(SIOCDARP, SIOCSRARP)
一般的和網絡有關的函數(SIOCGIFNAME, SIOCSIFADDR等等)
Goodies目錄中包含了很多展示ioctl用法的示例程式,看這些程式的時候,注意根據ioctl的指令類型來學習具體的調用參數結構,比如:和路由表相關的IOCTL用RTENTRY結構, rtentry結構是被定義在/usr/include/linux/route.h檔案中的,再一個和ARP相關的ioctl調用用到的arpreq結構被定義在/usr/include/linux/if_arp.h檔案之中.網絡接口相關的ioctl指令最具有代表性的特征為都是以S或G開頭,其實就是設定或得到資料, getifinfo.c程式用這些指令去讀取IP位址資訊,硬體位址資訊,廣播位址資訊,和與網絡接口相關的标志.對于這些ioctl,第三個參數是一個IFREQ結構體,這個結構體被定義在/usr/include/linux/if.h頭檔案中,在一些情況下,新的ioctl指令可能被需要(除了在那個頭檔案中被定義的之外),比如 WAVELAN無線網卡保持着無線信号強度的資訊,這些信西可能要 對使用者程式有用.使用者程式是怎麼通路到這些資訊的呢?我們的第一反應就是定義一個新的指令在sockios.h頭檔案中,比如SIOCGIFWVLNSS,不幸的是,這個指令在其他的網絡接口上是根本沒有意義的,另外試圖在其他接口上用這個名另而并非是在無線網口上用會出現違規通路,我們需要的是定義新特性接口指令的機理。幸運的是,LINUX作業系統為此目的内置了鈎子,如果你再看一下那個頭檔案sockios.h你會注意到每一個裝置都有一個預定義的SIOCDEVPRIVATE指令,實作它的任務就全權交給了寫這個裝置驅動的程式員了.根據正常約定,一個使用者程式調用一個特定的ioctl指令如下: ioctl(sockid, SIOCDEVPRIVATE, (char *) &ifr)這裡ifr是一個ifreq結構體變量,它用一個和這個裝置聯系的接口名稱填充ifr的ifr NAME域,比如,前述的無線網卡接口名稱為eth1。
不失一般性,一個使用者程式将同樣要與核心交換指令參數和操作結果,而這些已經通過一個域ifr.ifr_data的填充而做到了,比如,這個網卡的信号強度資訊被傳回到這個域當中。LINUX源代碼已經包含了兩個特殊裝置de4x5和ewrk3,他們定義和實作了特殊的ioctl指令.,這些裝置的源代碼在以下的檔案中:de4x5.h, de4x5.c, ewrk3.h, ewrk3.c, 他們兩個裝置都為在使用者空間和驅動間交換資料定義了他們自己的私有結構,在ioctl之前,使用者程式填充了需要的資料并且将ifr.ifr_data指向這個結構體.
我們在兩個驅動中走的更遠些進而進入代碼前,讓我們跟蹤一下處理ioctl系統調用的若幹步驟,,所有接口類型的ioctl請求都導緻dev_ioctl()被調用,這個ioctl僅僅是個包裝,大部分的真實的操作留給了dev_ifsioc().,這個dev_ioctl()要做的唯一一個事情就是檢查調用過程是否擁有合适的許可去核發這個指令,然後dev_ifsioc()首先要做的事情之一就是得到和名字域ifr.ifr_name中所對應的裝置結構,這在一個很大的switch語塊的代碼後實作。
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1273651