Linux系統程式設計(4)——檔案與IO之ioctl函式
ioctl是裝置驅動程式中對裝置的I/O通道進行管理的函式。所謂對I/O通道進行管理,就是對裝置的一些特性進行控制,例如串列埠的傳輸波特率、馬達的轉速等等。它的引數個數如下:int ioctl(int fd, int cmd, …);其中fd就是使用者程式開啟裝置時使用open函式返回的檔案標示符,cmd就是使用者程式對裝置的控制命令,至於後面的省略號,那是一些補充引數,一般最多一個,有或沒有是和cmd的意義相關的。ioctl函式是檔案結構中的一個屬性分量,就是說如果你的驅動程式提供了對ioctl的支援,使用者就能在使用者程式中使用ioctl函式控制裝置的I/O通道。
#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; // inputfrom user->kernel
struct ifreq *ifcu_req; //return of structures returned
}ifc_ifcu;
};
ioctl函式是I/O操作的雜物箱。幾乎所有的I/O操作都能用ioctl表示。終端I/O是ioctl的最大使用方面,主要用於裝置的I/O控制。ioctl用於向裝置發控制和配置命令,有些命令也需要讀寫一些資料,但這些資料是不能用read/write讀寫的,稱為Out-of-band資料。也就是說,read/write讀寫的資料是in-band資料,是I/O操作的主體,而ioctl命令傳送的是控制資訊,其中的資料是輔助的資料。例如,在串列埠線上收發資料通過read/write操作,而串列埠的波特率、校驗位、停止位通過ioctl設定,A/D轉換的結果通過read讀取,而A/D轉換的精度和工作頻率通過ioctl設定。
以下程式使用TIOCGWINSZ命令獲得終端裝置的視窗大小。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(void)
{
structwinsize size;
if(isatty(STDOUT_FILENO) == 0)
exit(1);
if(ioctl(STDOUT_FILENO,TIOCGWINSZ, &size)<0) {
perror("ioctlTIOCGWINSZ error");
exit(1);
}
printf("%drows, %d columns\n", size.ws_row, size.ws_col);
return0;
}
在圖形介面的終端裡多次改變終端視窗的大小並執行該程式,觀察結果。