Linux系統字符設備驅動框架筆記
不積跬步,何以至千里。掌握知識都是從很小的點開始的。下面是小編整理的Linux系統字符設備驅動框架筆記,歡迎閲讀!
字符設備是Linux三大設備之一(另外兩種是塊設備,網絡設備),字符設備就是字節流形式通訊的I/O設備,絕大部分設備都是字符設備,常見的字符設備包括鼠標、鍵盤、顯示器、串口等等,當我們執行 ls -l /dev 的時候,就能看到大量的設備文件, c 就是字符設備, b 就是塊設備,網絡設備沒有對應的設備文件。編寫一個外部模塊的字符設備驅動,除了要實現編寫一個模塊所需要的代碼之外,還需要編寫作為一個字符設備的代碼。
驅動模型
Linux一切皆文件,那麼作為一個設備文件,它的操作方法接口封裝在 struct file_operations ,當我們寫一個驅動的時候,一定要實現相應的接口,這樣才能使這個驅動可用,Linux的內核中大量使用"註冊+回調"機制進行驅動程序的編寫,所謂註冊回調,簡單的理解,就是當我們open一個設備文件的時候,其實是通過VFS找到相應的inode,並執行此前創建這個設備文件時註冊在inode中的'open函數,其他函數也是如此,所以,為了讓我們寫的驅動能夠正常的被應用程序操作,首先要做的就是實現相應的方法,然後再創建相應的設備文件。
#include //for struct cdev
#include //for struct file
#include //for copy_to_user
#include //for error number
/* 準備操作方法集 */
/*
struct file_operations {
struct module *owner; //THIS_MODULE
//讀設備
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//寫設備
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//映射內核空間到用户空間
int (*mmap) (struct file *, struct vm_area_struct *);
//讀寫設備參數、讀設備狀態、控制設備
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
//打開設備
int (*open) (struct inode *, struct file *);
//關閉設備
int (*release) (struct inode *, struct file *);
//刷新設備
int (*flush) (struct file *, fl_owner_t id);
//文件定位
loff_t (*llseek) (struct file *, loff_t, int);
//異步通知
int (*fasync) (int, struct file *, int);
//POLL機制
unsigned int (*poll) (struct file *, struct poll_table_struct *);
。。。
};
*/
ssize_t myread(struct file *filep, char __user * user_buf, size_t size, loff_t* offset)
{
return 0;
}
struct file fops = {
r = THIS_MODULE,
= myread,
...
};
/* 字符設備對象類型 */
struct cdev {
//public
struct module *owner; //模塊所有者(THIS_MODULE),用於模塊計數
const struct file_operations *ops; //操作方法集(分工:打開、關閉、讀/寫、...)
dev_t dev; //設備號(第一個)
unsigned int count; //設備數量
//private
...
};
static int __init chrdev_init(void)
{
...
/* 構造cdev設備對象 */
struct cdev *cdev_alloc(void);
/* 初始化cdev設備對象 */
void cdev_init(struct cdev*, const struct file_opeartions*);
/* 為字符設備靜態申請設備號 */
int register_chedev_region(dev_t from, unsigned count, const char* name);
/* 為字符設備動態申請主設備號 */
int alloc_chedev_region(dev_t* dev, unsigned baseminor, unsigned count, const char* name);
MKDEV(ma,mi) //將主設備號和次設備號組合成設備號
MAJOR(dev) //從dev_t數據中得到主設備號
MINOR(dev) //從dev_t數據中得到次設備號
/* 註冊字符設備對象cdev到內核 */
int cdev_add(struct cdev* , dev_t, unsigned);
...
}
static void __exit chrdev_exit(void)
{
...
/* 從內核註銷cdev設備對象 */
void cdev_del(struct cdev* );
/* 從內核註銷cdev設備對象 */
void cdev_put(stuct cdev *);
/* 回收設備號 */
void unregister_chrdev_region(dev_t from, unsigned count);
...
}
實現read,write
Linux下各個進程都有自己獨立的進程空間,即使是將內核的數據映射到用户進程,該數據的PID也會自動轉變為該用户進程的PID,由於這種機制的存在,我們不能直接將數據從內核空間和用户空間進行拷貝,而需要專門的拷貝數據函數/宏:
long copy_from_user(void *to, const void __user * from, unsigned long n)
long copy_to_user(void __user *to, const void *from, unsigned long n)
這兩個函數可以將內核空間的數據拷貝到回調該函數的用户進程的用户進程空間,有了這兩個函數,內核中的read,write就可以實現內核空間和用户空間的數據拷貝。
ssize_t myread(struct file *filep, char __user * user_buf, size_t size, loff_t* offset)
{
long ret = 0;
size = size > MAX_KBUF?MAX_KBUF:size;
if(copy_to_user(user_buf, kbuf,size)
return -EAGAIN;
}
return 0;
}
-
電腦有哪些操作系統?
提起操作系統,相信大家首選聯想的是電腦操作系統,下面小編就為大家介紹一下電腦有哪些操作系統吧!WINDOWS操作系統Windows操作系統是一款由美國微軟公司開發的窗口化操作系統。採用了GUI圖形化操作模式,比起從前的指令操作系統如DOS更為人性化。Windows操作系統是...
-
Win7純淨版出現藍屏代碼0xA0000001怎麼辦
Win7純淨版出現藍屏代碼0xA0000001怎麼辦?彆着急,先看看以下的辦法能不能解決問題,再決定是否找專業的人幫忙。解決方法:1、出現0xA0000001藍屏代碼,得得系統小編建議用户先查看系統藍屏日誌,通過日誌分析導致藍屏的原因,從而尋找解決方法。小編建議採用魔方藍屏助手...
-
win7怎樣取消開機密碼
用户在每次開機的時候都需要輸入密碼,還是顯得十分的麻煩,所以很多用户也就選擇了取消電腦的'開機密碼,那麼win7怎樣取消開機密碼呢,下面我們一起來看看吧。1、點擊開始菜單,點擊“控制面板”;2、將控制面板中的查看方式修改為“大圖標”,在下面找到“用户賬户”並...
-
Win8提示“已禁用IME”怎麼辦
Win8提示已禁用IME怎麼辦很多使用Win8的朋友可能遇到過系統右下角莫名其妙提示已經禁用IME的情況,那麼Win8提示已禁用IME怎麼辦?本文中筆者將為大家分享一下Win8提示已禁用IME究竟應該如何解決。IME是指InputMethodEditors輸入法編輯器,當在一段時間不用輸入法的...