前言
會寫這一篇主要是自己在看一些網路教材的時候如果有些資源比較久你就會發現他用的還是ioctl()
接口,但如果你實際上去碰新版的Kernel時卻發現了這個接口卻不見了,但卻多出了unlocked_ioctl()
和compat_ioctl()
這兩個很類似的function,然後就好奇他們到底差在哪裡、要怎麼用,學習完後就打了這篇文章做個記錄。
這篇文章就是對ioctl()
、 unlocked_ioctl()
和compat_ioctl()
三個做一個簡單的介紹,讓大家更能夠知道應該如何使用和區分他們。
(以下linux source code如果沒有特別提及版本,接以v4.1.14為主)
ioctl是什麼?
ioctl()
是撰寫driver一個很重要的接口,以字元裝置驅動(char device driver)來說,透過這個接口可以讓user來操作driver執行一些行為。
在撰寫driver code時,我們必須透過register_chrdev()
來向kernel註冊我們的driver。為此我們需要提供該driver的file_operation相關函數實作來讓user可以透過這些接口來操控該driver。
在/include/linux/fs.h中可以看到file_operations的結構定義:
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
| struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*mremap)(struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); ... };
|
常見需要實現的pointer to function包含open()
, read()
, write()
, close()
, ioctl()
…等,細節的部份我先不提。
主要來看ioctl()
這件事,上面是4.14版本的code,看了一下的code發現並沒有我說的ioctl()
,反而出現了unlocked_ioctl()
和compat_ioctl()
,到底發生了什麼事情呢?
Posted by John on
2020-10-24