Linux系統程式設計(4)——檔案與IO之ioctl函式

尹成發表於2014-07-24

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;
}


在圖形介面的終端裡多次改變終端視窗的大小並執行該程式,觀察結果。

 

 

 

 

 

 

相關文章