最近調試SmartCard驅動的時候發現ioctl返回值為-1,明明很正常的一個驅動,在別的地方都能正常跑,居然有問題;一直百思不得其解,開內核log,居然沒有執行到驅動設備Ioctl函數里面,第一時間想到的就是參數對不上,繼續查找,發現沒有問題,參數注冊都正常,char驅動open\read\write接口都沒有問題,居然只有這個ioctl有問題;繼續跟蹤file_operations結構,發現在這個結構中存在compat_ioctl,自從ioctl隨着BKL退出歷史的舞台之后,一直用到的是unlock_ioctl,這個compat_ioctl到底是干嘛的呢?本着對問題的研究精神,不放過任何一個可能性,我決定扒一扒compat_ioctl來歷;
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
在./Documentation/filesystems/vfs.txt中有一段描述:compat_ioctl: called by the ioctl(2) system call when 32 bit system calls are used on 64 bit kernels.
正常的情況下,對Ioctl的調用,會走unlock_ioctl,但在32位系統64位的內核上面會走compat_ioctl接口,這就是compat_ioctl存在的意義,由於我使用的Android系統位32位,內核編譯的是Arm64,這應該就是這個Bug產生的原因,果斷替換位compat_ioctl,問題解決;
關於compat_ioctl更詳細的解釋:http://lwn.net/Articles/119652/
綜上所述:在查找此類問題的時候,一定要多看源碼,從內核源碼里面尋找答案,很多時候看是無厘頭的錯誤后面必定隱藏着一個必然的解釋