ioctl配置IP地址 Linux核心實現分析
1 執行flow
本文以Linux kernel3.10版本描述
上圖是《Understanding LINUX NETWORK INTERNALS》一書中對socket的ioctl呼叫的整體flow,本文只對其中SIOCSIFADDR這一個command進行flow的梳理。
首先是socket的建立,這在上圖中沒有標識出來,大致flow如下圖所示,這部分原始碼在 net/socket.c中
socket的create對ioctl的作用主要有兩點:
1、如何在執行ioctl時,呼叫到sock_ioctl
在建立inode時,將socket_file_ops賦給inode→i_fop。這樣在執行ioctl時,通過執行在inode的函式指標,最終呼叫的就是sock_ioctl
如不理解上一句話,可參考如下解釋:
socket_file_ops 是socket 檔案中 file_operations結構體的實現的物件(全域性變數)。在每次create socket時,均將該全域性變數的指標賦給inode→i_fop.
每次執行ioctl時,是執行的inode→i_fop->(*unlocked_ioctl),而socket_file_ops→unlocked_ioctl 賦值是sock_ioctl函式的指標
所以每次在對socket執行ioctl時,最終執行的是sock_ioctl
該賦值在socket_alloc_file函式中實現,呼叫鏈是sock_map_fd →sock_alloc_file
2、如何根據SIOCSIFADDR,最終呼叫至inet_ioctl
在socket create時,會執行pf->create函式,該函式會將inet_ioctl函式指標賦值給sock->ops→ioctl
詳細說明:
pf通過socket create時的family,找到對應pf,執行其中的create函式。
family為AF_INET時,呼叫的create為 net/af_inet.c中的inet_create函式.
在pf→create函式中,通過type找到對應ioctl函式,賦值給sock->ops
type為SOCK_DGRAM時,對應ioctl為inet_ioctl
根據以上兩點大致可以理解在《Understanding LINUX NETWORK INTERNALS》一書中的socket 執行ioctl的flow
一開始,執行到sock_ioctl,該函式中根據cmd,執行sock→ops→ioctl
在上面2點可知,執行sock→ops→ioctl即執行inet_ioctl
inet_ioctl根據cmd,執行devinet_ioctl
所以最終執行的是devinet_ioctl函式
devinet_ioctl的實現在net/devinet.c中
devinet_ioctl函式的執行flow大致如下圖所示:
根據ifr.ifr_name的名稱,找到對應的in_device結構體,並找到對應的ifa結構體
將ifa重置ifaddr為設定ip,最後在重新新增至in_device結構體中。
SIOCGIFADDR 的flow便是將在找到ifa結構體後,將ifa中的addr set回sin_addr返回
2 資料結構
上部分主要寫了ioctl的執行flow和做了哪些事,可以看出,其中in_device與
in_device如下:
kernel network中比較重要的兩個結構體net_device和in_device,net_device主要用於核心自身(驅動以及上層協議等)對網路裝置的操作;
而in_device用於儲存使用者態對此裝置的配置,比如ip地址的配置等,儲存在in_device。兩個結構體通過指標互指聯絡在一起。