Linux中字符设备注册方式,3.4. 字符设备注册
3.4.?字符設備注冊
如我們提過的, 內核在內部使用類型 struct cdev 的結構來代表字符設備. 在內核調用你的設備操作前, 你編寫分配并注冊一個或幾個這些結構. [11]為此, 你的代碼應當包含 , 這個結構和它的關聯幫助函數定義在這里.
有 2 種方法來分配和初始化一個這些結構. 如果你想在運行時獲得一個獨立的 cdev 結構, 你可以為此使用這樣的代碼:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
但是, 偶爾你會想將 cdev 結構嵌入一個你自己的設備特定的結構; scull 這樣做了. 在這種情況下, 你應當初始化你已經分配的結構, 使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
任一方法, 有一個其他的 struct cdev 成員你需要初始化. 象 file_operations 結構, struct cdev 有一個擁有者成員, 應當設置為 THIS_MODULE. 一旦 cdev 結構建立, 最后的步驟是把它告訴內核, 調用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
這里, dev 是 cdev 結構, num 是這個設備響應的第一個設備號, count 是應當關聯到設備的設備號的數目. 常常 count 是 1, 但是有多個設備號對應于一個特定的設備的情形. 例如, 設想 SCSI 磁帶驅動, 它允許用戶空間來選擇操作模式(例如密度), 通過安排多個次編號給每一個物理設備.
在使用 cdev_add 是有幾個重要事情要記住. 第一個是這個調用可能失敗. 如果它返回一個負的錯誤碼, 你的設備沒有增加到系統中. 它幾乎會一直成功, 但是, 并且帶起了其他的點: cdev_add 一返回, 你的設備就是"活的"并且內核可以調用它的操作. 除非你的驅動完全準備好處理設備上的操作, 你不應當調用 cdev_add.
為從系統去除一個字符設備, 調用:
void cdev_del(struct cdev *dev);
顯然, 你不應當在傳遞給 cdev_del 后存取 cdev 結構.
3.4.1.?scull 中的設備注冊
在內部, scull 使用一個 struct scull_dev 類型的結構表示每個設備. 這個結構定義為:
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 */
};
我們在遇到它們時討論結構中的各個成員, 但是現在, 我們關注于 cdev, 我們的設備與內核接口的 struct cdev. 這個結構必須初始化并且如上所述添加到系統中; 處理這個任務的 scull 代碼是:
static void scull_setup_cdev(struct scull_dev *dev, int index)
{
int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}
因為 cdev 結構嵌在 struct scull_dev 里面, cdev_init 必須調用來進行那個結構的初始化.
3.4.2.?老方法
如果你深入瀏覽 2.6 內核的大量驅動代碼, 你可能注意到有許多字符驅動不使用我們剛剛描述過的 cdev 接口. 你見到的是還沒有更新到 2.6 內核接口的老代碼. 因為那個代碼實際上能用, 這個更新可能很長時間不會發生. 為完整, 我們描述老的字符設備注冊接口, 但是新代碼不應當使用它; 這個機制在將來內核中可能會消失.
注冊一個字符設備的經典方法是使用:
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
這里, major 是感興趣的主編號, name 是驅動的名子(出現在 /proc/devices), fops 是缺省的 file_operations 結構. 一個對 register_chrdev 的調用為給定的主編號注冊 0 - 255 的次編號, 并且為每一個建立一個缺省的 cdev 結構. 使用這個接口的驅動必須準備好處理對所有 256 個次編號的 open 調用( 不管它們是否對應真實設備 ), 它們不能使用大于 255 的主或次編號.
如果你使用 register_chrdev, 從系統中去除你的設備的正確的函數是:
int unregister_chrdev(unsigned int major, const char *name);
major 和 name 必須和傳遞給 register_chrdev 的相同, 否則調用會失敗.
[11]有一個早些的機制以避免使用 cdev 結構(我們在"老方法"一節中討論).但是, 新代碼應當使用新技術.
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Linux中字符设备注册方式,3.4. 字符设备注册的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 自动配置 mysql数据库,
- 下一篇: linux 其他常用命令