(dev_t)-->主設備號、次設備號 | MAJOR(dev_t dev) |
主設備號、次設備號-->(dev_t) | MKDEV(int major,int minor) |
在建立一個字元驅動時你的驅動需要做的第一件事是獲取一個或多個設備編號來使用.並且應當在不再使用它們時釋放它.
int register_chrdev_region(dev_t first, unsigned int count,char *name); //指定設備編號 |
安排主編號最好的方式, 我們認為, 是預設使用動態分配, 而留給自己在載入時或者甚至在編譯時指定主編號的選項權.
以下是在scull.c中用來獲取主設備好的代碼:
if (scull_major) { |
動態分配的缺點是你無法提前創建設備節點, 因為分配給你的模塊的主編號會變化. 對於驅動的正常使用, 這不是問題, 因為一旦編號分配了, 你可從 /proc/devices 中讀取它.
2、一些重要數據結構
大部分的基礎性的驅動操作包括 4 個重要的內核數據結構cdev,file_operations, file 和 inode.
file_operations結構定義在 <linux/fs.h>
struct file_operations scull_fops = { |
struct file,
struct inode ,是在內核內部用來表示文件的.因此, 它和代表打開文件描述符的文件結構是不同的. 可能有代表單個文件的多個打開描述符的許多文件結構, 但是它們都指向一個單個 inode 結構.
struct cdev ,Linux2.6內核與2.4內核不同2.6內核採用了.cdev結構體來描述管理字元設備
struct cdev {struct cdev *my_cdev = cdev_alloc();
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
cdev.owner = THIS_MODULE;
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
從系統中移除一個字元設備:void cdev_del(struct cdev *p)
以下是scull中的初始化代碼(之前已經為struct scull_dev 分配了空間):
/* |
open 方法提供給驅動來做任何的初始化來準備後續的操作. 在大部分驅動中, open 應當進行下面的工作:
●檢查設備特定的錯誤(例如設備沒準備好, 或者類似的硬體錯誤)
●如果它第一次打開, 初始化設備
●如果需要, 更新 f_op 指針.
●分配並填充要放進 filp->private_data 的任何數據結構
但是, 事情的第一步常常是確定打開哪個設備. 記住 open 方法的原型是:
int (*open)(struct inode *inode, struct file *filp); |
inode 參數有我們需要的信息
container_of(pointer, container_type, container_field); |
這個宏使用一個指向 container_field 類型的成員的指針, 它在一個 container_type 類型的結構中, 並且返回一個指針指向包含結構. 在 scull_open,
struct scull_dev *dev; /* device information */ |
識別打開的設備的另外的方法是查看51CTO提醒您,請勿濫發廣告!存儲在 inode 結構的次編號. 如果你使用 register_chrdev 註冊你的設備, 你必須使用這個技術. 確認使用
int scull_open(struct inode *inode, struct file *filp) |
release 方法
●釋放 open 分配在 filp->private_data
scull 的基本形式沒有硬體去關閉, 因此需要的代碼是最少的:
int scull_release(struct inode *inode, struct file *filp) |
本文出自 「sh411yy」 博客,請務必保留此出處http://sh411yy.blog.51cto.com/2993620/548496
[火星人 ] Linux字元驅動總結已經有560次圍觀