1. 程式人生 > >ioctl 用法(轉)

ioctl 用法(轉)

 檔案描述符是低層的輸入和輸出介面。描述符可以表示到裝置、管道或套接字的連線,這些連線用於與另一個程序或普通檔案進行通訊。I/O 控制 (ioctl) 函式呼叫可以用來對特殊檔案的基礎裝置引數進行操作。它們可以完成與開啟的檔案描述符相關聯的控制功能。這些命令涉及檔案、流、普通資料鏈路控制以及其他各種裝置。

  本文將討論 AIX Version 5.3 中提供的與網路操作和套接字相關的命令。在下列檔案中列出了與套接字相關的命令和結構:

  sys/ioctl.h

  net/if_arp.h

  net/if.h

  net/netopt.h

  netinet/in.h

  應用程式開發人員可以使用這些命令,並且在 AIX Version 5.3 的文件中對這些命令進行了詳細的描述。本文說明了有關 Internet Protocol Version 6 (IPv6) 地址和 Internet Protocol Version 4 (IPv4) 堆疊的常用命令的典型用法。

  使用 ioctl 套接字控制選項

  通常,網路程式需要了解系統中所有有關網路介面和 IP 地址的可用資訊。現在,未來的應用程式可以支援 IPv4 和 IPv6 雙協議棧。ioctl 結構需要對指標進行遍歷和操作,以處理 IPv4 和 IPv6 地址在長度上的差別(除了使用合適的套接字結構 sockaddr_in6 或 sockaddr_storage 之外)。

  AIX Version 5.3 提供了很多 ioctl 套接字控制選項,以提取各種有關網路介面的資訊。這些 ioctl 命令用於查詢介面的狀態並對其屬性進行操作。下面的部分中包含了一些有用的命令的程式碼段。有關 ioctl 命令的完整列表,請參見參考資料部分。

  ioctl 命令所使用的結構

  下面的清單介紹了一些最重要的結構,使用 ioctl 套接字命令時常常用到這些結構。

  清單 1. struct ifreq (/usr/include/net/if.h)

  struct ifreq {

  #ifndef IFNAMSIZ

  #define IFNAMSIZ    16

  #endif

  char  ifr_name[IFNAMSIZ];

  union {

  struct sockaddr ifru_addr;

  struct sockaddr ifru_dstaddr;

  struct sockaddr ifru_broadaddr;

  __ulong32_t   ifru_flags;

  int   ifru_metric;

  CADdr_t ifru_data;

  u_short ifru_site6;

  __ulong32_t  ifru_mtu;

  int   ifru_baudrate;

  } ifr_ifru;

  Following Macros are provided for convenIEnce

  #define ifr_addr    ifr_ifru.ifru_addr   

  #define ifr_dstaddr   ifr_ifru.ifru_dstaddr 

  #define ifr_broadaddr  ifr_ifru.ifru_broadaddr

  #define ifr_flags    ifr_ifru.ifru_flags  

  #define ifr_metric   ifr_ifru.ifru_metric  

  #define ifr_data    ifr_ifru.ifru_data   

  #define ifr_site6    ifr_ifru.ifru_site6  

  #define ifr_mtu     ifr_ifru.ifru_mtu   

  #define ifr_isno    ifr_ifru.ifru_data   

  #define ifr_baudrate  ifr_ifru.ifru_baudrate 

  };  

  清單 2. struct ifconf (/usr/include/net/if.h)  

  struct ifconf {

  int   ifc_len;        

  union {

  caddr_t ifcu_buf;

  struct ifreq *ifcu_req;

  } ifc_ifcu;

  Following macros are provided for convenience

  #define ifc_buf ifc_ifcu.ifcu_buf   

  #define ifc_req ifc_ifcu.ifcu_req   

  };

  程式碼示例

  下面的表 1 介紹了一些介面檢索命令。該資訊來源於 IBM System p 和 AIX。

  表 1. 介面檢索命令

  ioctl 命令描述

  SIOCGSIZIFCONF 獲得獲取 SIOCGIFCONF 返回的所有介面的配置資訊所需的記憶體。

  ioctl(fd, SIOCGSIZIFCONF, (caddr_t)&ifconfsize);

  int ifconfsize;

  SIOCGIFADDR

  SIOCSIFADDR

  SIOCGIFADDR 獲取介面地址,而 SIOCSIFADDR 設定介面地址。ifr.ifr_addr 欄位返回地址。

  ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));

  ioctl(fd, SIOCSIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));

  struct ifreq ifr;

  SIOCGIFCONF 返回系統中配置的所有介面的配置資訊。

  ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc);

  struct ifconf ifconf;

  SIOCGSIZIFCONF

  下面的程式碼段可以獲取用來填充所有配置介面的資訊所需的緩衝區大小。

  清單 3. 使用 SIOCGSIZIFCONF 獲得所需的緩衝區大小

  int get_interface_size(int sd){

  int ret,size;

  ret=ioctl(sd,SIOCGSIZIFCONF,&size);

  if(ret==-1){

  perror("Error getting size of interface :");

  return ret;

  }

  return size;

  }

  main

  {

  struct ifconf ifc;

  int sd;

  sd=socket(AF_INET6,SOCK_DGRAM,0);

  printf("Size of memory needed = %d",get_interface_size(sd));

  }

  上面程式碼的輸出是:

  $> ./myprog

  Size of memory needed = 628

  SIOCGIFCONF 和 SIOCGIFADDR

  SIOCGIFCONF 和 SIOCGIFADDR 命令可以用來檢索介面的地址。SIOCGIFCONF 可以用來獲取所有配置介面的資訊,SIOCGIFADDR 可以用來檢索特定介面的地址。

  清單 4. 使用 SIOCGIFCONF 獲取配置資訊

  int alloc_buffer_size(int sd,struct ifconf *ifc){

  int ret=-1,bsz=sizeof(struct ifreq);

  int prevsz=bsz;

  ifc->ifc_req=NULL;

  ifc->ifc_len=bsz;

  do{

  ifc->ifc_req=(struct ifreq *)realloc(ifc->ifc_req,bsz);

  if(!ifc->ifc_req){

  perror("Malloc failed :");

  return ret;

  }

  ifc->ifc_len=bsz;

  ret=ioctl(sd,SIOCGIFCONF,(caddr_t)ifc);

  if(ret==-1){

  perror("Error getting size of interface :");

  return ret;

  }

  if(prevsz==ifc->ifc_len)

  break;

  else{

  bsz*=2;

  prevsz=(0==ifc->ifc_len ? bsz : ifc->ifc_len) ;

  }

  }while(1);

  ifc->ifc_req=(struct ifreq *)realloc(ifc->ifc_req,prevsz);

  return ifc->ifc_len;

  }

  在使用 ifreq 結構中的配置資訊填充了列表之後,可以對其進行遍歷以檢索所需的資料。根據呼叫之後該結構中填充的套接字地址的長度,可以對這個指標進行移動。下面的清單 5 顯示了上面程式碼的列表中獲得的系統中可用的 IP。

  清單 5. 從配置列表中檢索資訊

  #define MAX(x,y) ((x) >(y) ? (x) : (y))

  #define SIZE(p) MAX((p).sa_len, sizeof(p))

  void print_ips(struct ifconf *ifc){

  char *cp,*cplim,addr[INET6_ADDRSTRLEN];

  struct ifreq *ifr=ifc->ifc_req;

  cp=(char *)ifc->ifc_req;

  cplim=cp+ifc->ifc_len;

  for(;cpifr_name) + SIZE(ifr->ifr_addr))){

  ifr=(struct ifreq *)cp;

  printf("%s :",ifr->ifr_name);

  getip(ifr,addr);

  printf("%s",addr);

  }

  return ;

  }

  main

  {

  struct ifconf ifc;

  int sd;

  sd=socket(AF_INET6,SOCK_DGRAM,0);

  alloc_buffer_size(sd,&ifc);

  print_ips(&ifc);

  }

  上面程式碼的輸出是:

  $> ./myprog

  en0 :6.3.6.0

  en0 :9.182.192.169

  en0 :fe80::209:6bff:feeb:70b2

  sit0 :1.4.4.0

  sit0 :::9.182.192.169

  lo0 :24.3.0.0

  lo0 :127.0.0.1

  lo0 :::1

  清單 6. 使用 SIOCGIFADDR 獲取介面地址

  void getip(struct ifreq *ifr,char *addr){

  struct sockaddr *sa;

  sa=(struct sockaddr *)&(ifr->ifr_addr);

  switch(sa->sa_family){

  case AF_INET6:

  inet_ntop(AF_INET6,(struct in6_addr *)&(((struct sockaddr_in6 *)sa)->sin6_addr),

  addr,INET6_ADDRSTRLEN);

  break;

  default : strcpy(addr,inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));

  }

  return;

  }

  main

  {

  char netaddr[INET_ADDRSTRLEN];

  int sd;

  sd=socket(AF_INET,SOCK_DGRAM,0);

  strcpy(ifr.ifr_name,"en0");

  if((ioctl(sd,SIOCGIFADDR,(caddr_t)&ifr,sizeof(struct ifreq)))<0)

  perror("Error : ");

  getip(&ifr,netaddr);

  printf("%s",netaddr);

  }

  上面程式碼的輸出是:

  $./myprog

  9.182.192.35

  下面的表 2 介紹了介面標誌和一些屬性檢索命令。

  表 2. 介面標誌和屬性檢索命令

  ioctl 命令描述

  SIOCGIFFLAGS

  SIOCSIFFLAGS

  SIOCGIFFLAGS 可以獲取介面標誌。

  SIOCSIFFLAGS 可以設定介面標誌。

  ioctl(fd, cmd, (caddr_t)&ifr);

  struct ifreq ifr;

  SIOCGIFFLAGS

  在使用 SIOCGIFCONF 獲取了介面列表之後,您可以使用 SIOCGIFFLAGS-SIOCSIFFLAGS 對來獲取和設定介面的屬性。介面標誌表示為 IFF_XXX。有關完整的列表,請參閱檔案 /usr/include/net/if.h。

  下面的示例使用一對介面標誌來檢索其當前狀態,並檢查環回。也可以使用其他選項。

  清單 7. 驗證介面的狀態和型別

  for(;cp

  ifr=(struct ifreq *)cp;

  cp+=(sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr));

  printf("%-9s ",ifr->ifr_name);

  ret=ioctl(sd,SIOCGIFFLAGS,(caddr_t)ifr);

  if(ret==-1){

  perror("Error getting flags for interface :");

  return ;

  }

  if((ifr->ifr_flags)&IFF_UP)

  printf("UP");

  else printf("DOWN");

  if((ifr->ifr_flags)&IFF_LOOPBACK)

  printf(",Loopback");

  printf("");

  }

  上面程式碼的輸出是:

  $> ./myprog

  en0    UP

  en0    UP

  en0    UP

  sit0    UP

  sit0    UP

  lo0    UP,Loopback

  lo0    UP,Loopback

  lo0    UP,Loopback

  清單 8. 設定介面標誌

  Partial output of ifconfig before setting the flag

  sit0: flags=4900041

  inet6 ::9.182.192.169/96

  Code to set the interface flag

  int set_interface_flag(int sd,short flag,char *interface){

  struct ifreq ifr;

  int oldflags;

  strcpy(ifr.ifr_name,interface);

  if((ioctl(sd,SIOCGIFFLAGS,(caddr_t)&ifr))==-1){

  perror("Error getting interface flags :");

  return -1;

  }

  printf("Setting new interface flag 0X%x",flag);

  ifr.ifr_flags|=flag;

  if((ioctl(sd,SIOCSIFFLAGS,(caddr_t)&ifr))==-1){

  perror("Error setting interface flags :");

  return -1;

  }

  return 0;

  }

  main

  {

  int sd;

  sd=socket(AF_INET6,SOCK_DGRAM,0);

  set_interface_flag(sd,IFF_NOTRAILERS,"sit0");

  }

  上面程式碼的輸出是:

  You must have permission to change the flag

  $./myprog

  Setting new interface flag 0X20

  $ifconfig -a

  .............

  .............

  sit0: flags=4900061

  inet6 ::9.182.192.169/96

  .............

  .............

  表 3 介紹了一些用於網路優化的命令。

  表 3. 用於網路優化的命令

  ioctl 命令描述

  SIOCGIFMTU SIOCGIFMTU 可以獲取介面的最大傳輸單元 (MTU)。

  ioctl(fd, cmd, (caddr_t)&ifr);

  struct ifreq ifr;

  這個 MTU 值儲存在 ifr.ifr_mtu 欄位中。

  SIOCGNETOPT

  SIOCGNETOPT1

  SIOCGNETOPT 可以獲取一個網路選項的值。

  ioctl(fd, cmd, (caddr_t)&oreq);

  struct optreq oreq;

  SIOCGNETOPT1 可以獲取當前值、預設值和網路選項的範圍。

  ioctl(fd, SIOCGNETOPT1, (caddr_t)&oreq);

  struct optreq1 oreq;

  SIOCGIFMTU

  清單 9. 從 ifreq 結構獲取 MTU

  ret=ioctl(sd,SIOCGIFMTU,ifr);

  if(ret==-1){

  perror("Error getting mtu for interface :");

  return ;

  }

  printf(" %d",ifr->ifr_mtu);

  SIOCGNETOPT1

  SIOCGNETOPT1 給出當前值、預設值和網路選項的範圍。

  清單 10. 從 optreq1 結構獲取網路選項

  int print_network_options(int sd){

  int ret;

  struct optreq1 oreq;

  oreq.getnext=1;

  while((ioctl(sd,SIOCGNETOPT1,(caddr_t)&oreq))!=-1)

  printf("%s = %s",oreq.name,oreq.data);

  return 0;

  }

  上面程式碼的輸出是:

  $> ./myprog

  arpqsize = 12

  arpt_killc = 20

  arptab_bsiz = 7

  arptab_nb = 149

  ........

  ........

  ........

  ........

  ifsize = 256

  inet_stack_size = 16

  ip6_defttl = 64

  ........

  在 AIX 中,您還可以使用 no 命令來管理各種網路優化引數。有關更詳細的資訊,請參閱相應的 man 頁面。

  清單 11. AIX 計算機上“no”命令的輸出

  $> no -a|more

  arpqsize = 12

  arpt_killc = 20

  arptab_bsiz = 7

  arptab_nb = 149

  bcastping = 0

  clean_partial_conns = 0

  delayack = 0

  delayackports = {}

  dgd_packets_lost = 3

  dgd_ping_time = 5

  dgd_retry_time = 5

  directed_broadcast = 0

  extendednetstats = 0

  fasttimo = 200

  ........

  ........

  總結

  ioctl 命令的功能非常強大,您可以使用它們來訪問或修改網路(或其他)裝置的可配置引數。它們使用了各種各樣的資料結構,應該使用正確的資料來填充這些資料結構,以便實現預期的結果。您將發現在使用 AF_INET 和 AF_INET6 系列時存在的區別。本文提供了一小部分常用命令子集的程式碼示例。要獲得 AIX Version 5.3 中完整的命令清單,請轉到參考資料部分。我們希望這些關於 ioctl 的資訊對您有用。

最後補上一個用ioctl獲取本機ip地址的例子

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <net/if.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>

 

int main()

{
    int i=0;
    int sockfd;
  struct ifconf ifconf;
  unsigned char buf[512];
  struct ifreq *ifreq;
  //初始化ifconf
  ifconf.ifc_len = 512;
  ifconf.ifc_buf = buf;
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
    {
        perror("socket");
        exit(1);
    } 
  ioctl(sockfd, SIOCGIFCONF, &ifconf);    //獲取所有介面資訊
  //接下來一個一個的獲取IP地址
  ifreq = (struct ifreq*)buf; 
  for(i=(ifconf.ifc_len/sizeof(struct ifreq)); i>0; i--)
  {
//      if(ifreq->ifr_flags == AF_INET){            //for ipv4
      printf("name = [%s]\n", ifreq->ifr_name);
      printf("local addr = [%s]\n", inet_ntoa((((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr).s_addr));
      ifreq++;

//  }

  }
    return 0;
}

相關推薦

ioctl 用法

 檔案描述符是低層的輸入和輸出介面。描述符可以表示到裝置、管道或套接字的連線,這些連線用於與另一個程序或普通檔案進行通訊。I/O 控制 (ioctl) 函式呼叫可以用來對特殊檔案的基礎裝置引數進行操作。它們可以完成與開啟的檔案描述符相關聯的控制功能。這些命令涉及檔案、流、普

__cplusplus的用法

縮進 def com 頭文件 需要 c/c++ bsp c++編譯 可能 經常在/usr/include目錄下看到這種字句: #ifdef __cplusplusextern "C" {#endif...#ifdef __cplusplus}#endif 不太明白是

oracle nologging用法

而是 array 類型 無效 data 還得 模式 dddd reat 一、oracle日誌模式分為(logging,force logging,nologging) 默認情況是logging,就是會記錄到redo日誌中,force logging是強制記錄日誌,nolog

el 表達式用法

dex 循環 function 大致 哪裏 字符串 用戶 不同 ken el 表達式用法(轉) 1、EL簡介 1)語法結構 ${expression} 2)[]與.運算符 EL 提供.和[]兩種運算符來存取數據。 當要存取的屬

phpcms標簽用法

dot 指定 listorder 萬能 省略號 upd 關聯 blank bsp 1.顯示指定catid的欄目名稱和鏈接 {$CATEGORYS[25][‘catname‘]} {$CATEGORYS[25][‘url‘]} 獲取父欄目id/獲取父欄目名稱 $CATEG

java中正則表達式基本用法

code ack acea print 表達式 劃線 跟著 以及 n) https://www.cnblogs.com/xhj123/p/6032683.html 正則表達式是一種可以用於模式匹配和替換的規範,一個正則表達式就是由普通的字符(例如字符a到z)以及特殊字符(元

關於重定向RedirectAttributes的用法

richtext ... redirect 傳參 body code path cnblogs control 原文地址:https://zhuanlan.zhihu.com/p/21353217?refer=pengsong-java RedirectAttributes

Linux c —— opendir函數和readdir函數內涵及用法

har code pan 接下來 () cat AD con size_t opendir函數 頭文件:#include <sys/types.h> #include <dirent.h> 函數:DIR *opendir(const char *n

Linux date命令的用法

字符 系統 顯示日期 文件夾 函數 block 只需要 sat 小時 1、顯示時間 date命令可以按照指定格式顯示日期,只鍵入date則以默認格式顯示當前時間。如下: 如果需要以指定的格式顯示日期,可以使用“+”開頭的字符串指定其格式,詳細格式如下: %n : 下一行

UpdateData的用法

原文轉自 https://blog.csdn.net/ddjj_1980/article/details/51452289   UpdateData(TRUE)——重新整理控制元件的值到對應的變數。(外部輸入值交給內部變數)即:控制元件的值—>變數。UpdateData(FALSE)——

scala中sorted,sortby,sortwith的用法

scala中sorted,sortWith,sortBy用法詳解 2017年07月23日 23:07:51 bitcarmanlee 閱讀數:9249 版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/bitcarmanle

c++STL map用法

此文章源於博主(sunshinewave),轉到自己部落格以後方便檢視 map是STL的一個關聯容器,它提供一對一(其中第一個可以稱為關鍵字,每個關鍵字只能在map中出現一次,第二個可能稱為該關鍵字的值)的資料處理能力,由於這個特性,它完成有可能在我們處理一對一

pthread_mutex_lock用法

條件變數      條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個動作:一個執行緒等待"條件變數的條件成立"而掛起;另一個執行緒使"條件成立"(給出條件成立訊號)。為了防止競爭,條件變數的使用總是和一個互斥鎖結合在一起。  

Java產生隨機數用法及基本用法

1.隨機產生四位數[1000,9999] num=(int)(Math.random()*9000)+1000; Math.random()方法是產生double型[0,1)的資料,[0,1)*9000=[1,9001),用int型別強轉後便是[0,8999], 因而可以得到1000~9

NetworkX的基本用法

在PythonWin 的Shell裡輸入:import networkx as nx                            #匯入NetworkX包,為了少打幾個字母,將其重新命名為nxG = nx.Graph()                                       

main函式中兩個引數的用法

main函式中兩個引數的用法 MSDN6.0中寫道:argc is An integer specifying how many arguments are passed to the program from the command line. Because the program name is co

where、having之間的區別和用法

聚合函式是比較where、having 的關鍵。  開門見山。where、聚合函式、having 在from後面的執行順序: where>聚合函式(sum,min,max,avg,count)>having 列出group by來比較二者。()因

14、SQL Server:sql update set from 的用法

本文來自:http://www.cnblogs.com/zhang9418hn/archive/2012/03/21/2409551.html 下面是這樣一個例子:  兩個表a、b,想使b中的memo欄位值等於a表中對應id的name值      表a:id, nam

Java 列舉(enum) 詳解7種常見的用法

原文:https://blog.csdn.net/qq_27093465/article/details/52180865JDK1.5引入了新的型別——列舉。在 Java 中它雖然算個“小”功能,卻給我的開發帶來了“大”方便。大師兄我又加上自己的理解,來幫助各位理解一下。用法

gnome-terminal 快捷鍵基本用法

1 總結一下在GNOME桌面下面鍵盤的使用方法: 2  3 虛擬命令終端: 4 //開啟虛擬終端 5 <alt> + <F2>, 輸入gnome-terminal 6  7 //新增標籤頁 8 <shift> + <ctrl> + <T> 9  1