[英]Getting ENOTTY on ioctl for a Linux Kernel Module
我定義了以下chardev:
。H
#define MAJOR_NUM 245
#define MINOR_NUM 0
#define IOCTL_MY_DEV1 _IOW(MAJOR_NUM, 0, unsigned long)
#define IOCTL_MY_DEV2 _IOW(MAJOR_NUM, 1, unsigned long)
#define IOCTL_MY_DEV3 _IOW(MAJOR_NUM, 2, unsigned long)
.c模塊
static long device_ioctl(
struct file* file,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
...
}
static int device_open(struct inode* inode, struct file* file)
{
...
}
static int device_release(struct inode* inode, struct file* file)
{
...
}
struct file_operations Fops = {
.open=device_open,
.unlocked_ioctl= device_ioctl,
.release=device_release
};
static int __init my_dev_init(void)
{
register_chrdev(MAJOR_NUM, "MY_DEV", &Fops);
...
}
module_init(my_dev_init);
我的用戶代碼
ioctl(fd, IOCTL_MY_DEV1, 1);
總是失敗,並出現相同的錯誤: ENOTTY
設備不正確的ioctl
我見過類似的問題:
但是他們的解決方案對我不起作用
當您的設備驅動程序尚未注冊要調用的ioctl函數時,內核會發出ENOTTY
。 恐怕您的函數未正確注冊,可能是因為您已在struct file_operations
結構的.unlocked_ioctl
字段中注冊了它。
如果在功能的鎖定版本中注冊它,可能會得到不同的結果。 最可能的原因是索引節點被鎖定以進行ioctl調用(應該這樣做是為了避免競爭條件,同時對同一設備進行read
或write
操作)
抱歉,我無法使用要使用的字段的正確名稱訪問linux源代碼樹,但是可以肯定的是,您可以自己找到它。
我觀察到您使用了宏_IOW
,並將主數字用作唯一標識符。 這可能不是您想要的。 _IOW
第一個參數試圖確保ioctl調用獲得唯一標識符。 沒有通用的方法來獲取此類標識符,因為這是您在應用程序代碼和內核代碼之間創建的接口協定。 因此,使用主號碼是不好的做法,原因有兩個:
_IOW
是很久以前(從Linux內核誕生之日起)構建的宏,它試圖解決此問題,方法是允許您為每個驅動程序選擇一個不同的字符(但不依賴於其他內核參數,原因已指出)對於具有ioctl調用且未與其他設備驅動程序沖突的設備。 發生這種沖突的可能性很小,但是發生這種情況時,可能會導致機器狀態不正確(您已向錯誤的設備發出了有效的,有效的ioctl調用)
古代的unix(和早期的linux)內核使用不同的字符來構建這些調用,因此,例如, tty
驅動程序將'T'
用作_IO*
宏的參數,scsi磁盤使用了'S'
等。
我建議您選擇一個隨機數(不在Linux內核列表中的其他位置出現),然后在所有設備中使用它(可能編寫的驅動程序比內核中的驅動程序少),並為每個ioctl選擇一個不同的ioctl id呼叫。 用這種方式用已注冊的ioctl維護本地ioctl文件比嘗試猜測始終有效的值要好得多。
另外,看看_IO*
宏的定義應該是非常說明性的:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.