- LDD3一次配置多個device,對多個device視為同一類,使用同一個module
- 宋寶華一開始只有一個device,只給定一個module
兩者之間的差異決定的對程式展現的方式,其中以container_of這個macro最為經典,建議先看完宋寶華的範例,再瀏覽LDD3的範例,可以知道這個macro的關鍵性作用
LDD3展示了,一個module可以同時為同一類的裝置提供驅動程式,讓device(裝置)與operations(操作),可以結合,同時可以分開,一個module提供多個裝置,相同的操作,其中隱含了物件或者說ADT(abstract data type)的概念,這個在driver開方上很重要,udev更是把這種概念發揚光大
inode跟file兩個重要的結構提供了不同的作用,inode大多存在於kernel space,file則是user/kernel space都有(使用者一般操作file),同時也是支撐VFS (virtual file system)的兩個重要結構
- file結構有兩個重要成員,一個是file_operations,也就是操作file的functions,另外一個是private_data指標,通常module會將對應的device資料的記憶體位置交給private_data
- inode則擁有i_cdev或者i_bdev,分別表示character device或者block device這兩個指標,雖然一般開發者會重新包裝自己的結構,將struct cdev包裝起來,以支援定義的驅動程式,如LDD3範例
struct scull_dev {
struct scull_qset *data; /* Pointer to first quantum set */
int quantum; /* the current quantum size */
int qset; /* the current array size */
unsigned long size; /* amount of data stored here */
unsigned int access_key; /* used by sculluid and scullpriv */
struct semaphore sem; /* mutual exclusion semaphore */
struct cdev cdev; /* Char device structure */
};
struct scull_dev *scull_devices; /* allocated in scull_init_module */
最後一個scull_devices表示一堆同類的devices
有了以上的瞭解之後來看open、read函數
static int open(struct inode *inode,struct file *filp){
...
}
static ssize_t read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){
...
}
在LDD3的範例在init函數配置好了所有的scull dev(因為不只一個device),但是在open函數的時候要如何找到對應的scull_devices中的哪一個?因為我們想把他assign給file.private_data方便以後給read函數使用
一般而言,由於inode包含了cdev這個變數,我們知道cdev來自於scull_dev裡面,所以會想藉此找出scull_dev,裡面包含了如何計算cdev應該在scull_dev內的位移,配合位移,藉由調整記憶體的address,我們就可以找到scull_dev了,而此時container_of就可以幫我們忙
struct scull_dev *dev; /* device information */
dev = container_of(inode->i_cdev, struct scull_dev, cdev);
filp->private_data = dev; /* for other methods */
constainer_of這個macro會自動完成計算位移以及轉型的動作,將目前打開的device所指向的scull_dev變數找出來。也就是只有scull_device.cdev結構成員,卻可以找到scull_dev的結構變數。做了那麼多工作,就是為了把scull_device配置給filp->private_data,後面read函數就可以應用她了
如果今天只有一個device,那麼其實也不用那麼麻煩,就如宋寶華的範例,直接將struct scull_dev onlyone設定為global變數,然後直接在open函數的時候assign給filp->private_data即可
由上面可以了解到,LDD3在一個範例內展示了
- VFS這樣的抽象操作需要file以及inode配合
- scull這個module可以同時支援多個一樣的裝置
- 如何註冊character device,以及要注意的事項
- 如何實作file operations
- 隱含在Linux Device Driver中分層以及分工的架構
- ...
不細看還真的很難體驗這個module竟然有如此多的東西,也感嘆這章節竟然寫得如是簡單/簡潔,真的不知道LDD3的作者是故意的還是假設讀者的Linux背景很夠
如果有興趣了解container_of到底如何運作,可以參考參考資料連結
參考資料:
http://space.itpub.net/14805538/viewspace-445624
http://tw.myblog.yahoo.com/hughes-blog/article?mid=88&prev=-1&next=87
沒有留言:
張貼留言