理解驅動程序中的ioctl

原型:
  1. int ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);
當第一次看到驅動程序中的ioctl時,被它那大量的case所迷惑了。不是它的量大,而是應該怎樣設定其中的分支爲應用程序提供統一的入口參數,也就是說和其他驅動中ioctl的規則保持一致。
ioctl中第一個參數和第二個參數很明白。
要很好的編寫驅動ioctl,就需要理解第三個參數cmd。
找到內核內核代碼 include/asm/ioctl.h 中的相關定義和描述,就會明白應該按照什麼規則來設定。
目前cmd是一個32位無符號整數,被分爲4個字段。從高到底分別爲
| dir | size | type | nr |
dir: 2bit,命令指示,表示命令類型
size: 14bit,數據大小,通常和第四個參數有關
type: 8bit,類型,又稱之爲幻數,表示設備的類型
nr: 8bit,命令序號。
各個字段的順序和位寬可能在不同版本、不同平臺的內核中是不同的,寫內核模塊時應使用內核提供的宏來作處理,而不直接設定。
當然這個cmd的規定對驅動程序來說並不是嚴格的,也可另起爐竈,但是這不好。
相對於驅動程序中的ioctl就是應用程序中的ioctl,其原型是:
ioctl (int __fd, unsigned long int __request, ...)
其中int __fd 是已經打開的文件描述符。
int __request 是請求命令字,這是與設備相關的,也就是對應驅動程序ioctl中的cmd
第三個參數依賴於第二個參數,通常是一個指針,或有或無。
同樣對應用程序的request的設定也應使用相應的宏來處理,參看 /asm-generic/ioctl.h
下面以ldd3中提供的scull設備爲對象,在應用程序中調用ioctl對其進行控制。
  1. int main(void)
  2. {
  3.  int fd = open("/dev/scull",O_RDONLY);
  4.  int qset_size = 2000;
  5.  if(fd<0){
  6.   printf("error/n");
  7.   return 0;
  8.  }
  9.  ioctl(fd, _IO('k',0) ); // 其中k是scull設備的類型
  10.  // 這條命令是復位scull設備中量子和量子集的大小。
  11.  printf("%d/n", ioctl(fd,_IO('k',8) ) ); // 獲取默認量子集大小
  12.  ioctl(fd, _IOW('k',2,int), &qset_size ); // 更改量子集大小
  13.  printf("%d/n", ioctl(fd,_IO('k',8) ) );
  14.  close(fd);
  15.  return 0;
  16. }

實際上,這裏調用宏函數來設定request,只是爲了更清晰的瞭解如何設定request( 也就是設定驅動程序中的cmd),
而在應用程序中通常是直接給出其值。比如ioctl(sock, SIOCGIFNAME, &ifr)來獲取接口名.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章