Linux驱动编程 step-by-step (二) 简单字符设备驱动
生活随笔
收集整理的這篇文章主要介紹了
Linux驱动编程 step-by-step (二) 简单字符设备驱动
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
簡單字符設備驅動
1、主次設備號
主設備號標識設備連接的的驅動,此設備好由內核使用,標識在相應驅動下得對應的設備
在linux中設備號是一個32位的dev_t類型
typedef?__u32????__kernel_dev_t;
typedef?__kernel_dev_t????dev_t;
crw-------?1?root??root??10,?1?Apr?11??2011?psaux?
crw-------?1?root??root??4,??1?Oct?2803:04?tty1?
crw-rw-rw-?1?root??tty???4,?64?Apr?11??2011?ttys0?
crw-rw----?1?root??uucp??4,?65?Apr?11??2011?ttyS 上圖是再/dev目錄下用$ls -l 命令顯示的部分結果可以看到tty driver的主設備號都為4(各個系統版本有差別),次設備號不同
由主次設備號生成設備號
可以使用宏MKDEV
dev_t ?dev_num = MKDEV(dev_t major, dev_t minor);
2、分配與釋放設備號
/*??靜態分配設備號???? ?*??parameter:???????? ?*??????first?:?分配的第一個設備號?? ?*??????count:?分配的設備個數?? ?*??????name?:?設備名?? ?*??return?value:?? ?*??????0:?success?? ?*??????負值:出現錯誤,錯誤碼?? */?? int?register_chrdev_region(dev_t?first,?unsigned?int?count,?char?*name); ?? ?? /*??動態分配設備號???? ?*??parameter:???????? ?*??????dev?:?用來存儲分配的設備號值?? ?*??????firstminor:?次設備號(一般填0)?? ?*??????count:?分配的設備個數?? ?*??????name?:?設備名?? ?*??return?value:?? ?*??????0:?success?? ?*??????負值:出現錯誤,錯誤碼?? */?? int?alloc_chrdev_region(dev_t?*dev,?unsigned?int?firstminor,?unsigned?int?count,?char?*name); ?? ?? /*??釋放設備號?? ?*??parameter:???????? ?*??????first:?設備號?? ?*??????count:?分配的設備個數?? */?? void?unregister_chrdev_region(dev_t?first,?unsigned?int?count);??
#include?<linux/init.h>??? #include?<linux/module.h>??? #include?<linux/types.h>??? #include?<linux/fs.h>??? ?? #define?SIMPLE_DEBUG?1??? #define?DEV_COUNT?2??? #define?SIMPLE_NAME?"simple_char"??? ?? static?int?simple_major?=?108; ?? static?int?simple_minor?=?0; ?? ?? static?__init?int?simple_init(void) ?? { ?? ????dev_t?dev; ?? ????int?err; ?? #if?SIMPLE_DEBUG??? ????printk(KERN_INFO?"In?%s\n",?__func__); ?? #endif??? ????dev?=?MKDEV(simple_major,?simple_minor);?//求取設備號?? ????if(dev?>?0)//設備號有效?? ????{ ?? #if?SIMPLE_DEBUG??? ????????printk(KERN_INFO?"try?to?register?static?char?dev??%d?\n",?dev); ?? #endif??? ????????err?=?register_chrdev_region(dev,DEV_COUNT,?SIMPLE_NAME);?//靜態分配設備號?? ????????if(err?<?0)?//靜態分配出錯?嘗試使用動態分配?? ????????{ ?? ????????????printk(KERN_WARNING?"register?static?char?dev?error\n"); ?? ????????????err?=?alloc_chrdev_region(&dev,?0,?DEV_COUNT,?SIMPLE_NAME);?//動態分配設備號?? ????????????if(err?<?0) ?? ????????????{ ?? ????????????????printk(KERN_ERR?"register?char?dev?error?in?line?%d\n",__LINE__); ?? ????????????????goto?error; ?? ????????????} ?? ????????????else?? ????????????{ ?? ????????????????simple_major?=?MAJOR(dev);//重新計算主設備號?? ????????????????simple_minor?=?MINOR(dev);//重新計算此設備號?? ????????????} ?? ???????????? ?? ????????} ?? ????????else{ ?? ???????? ?? ????????} ?? ????} ?? ????else?//設備號無效使用動態分配?? ????{? ?? #if?SIMPLE_DEBUG??? ????????printk(KERN_INFO?"try?to?register?alloc?char?dev??\n"); ?? #endif??? ????????err?=?alloc_chrdev_region(&dev,?0,?DEV_COUNT,?SIMPLE_NAME); ?? ????????if(err?<?0) ?? ????????{ ?? ????????????printk(KERN_ERR?"register?char?dev?error?in?line?%d\n\n",__LINE__); ?? ????????????goto?error; ?? ????????} ?? ????????else?? ????????{ ?? ????????????simple_major?=?MAJOR(dev); ?? ????????????simple_minor?=?MINOR(dev); ?? ????????} ?? ?? ????} ?? ?? #if?SIMPLE_DEBUG??? ????printk(KERN_INFO?"register?char?dev?success?major?=?%d?minor?=?%d?\n",?simple_major,?simple_minor); ?? #endif??? ?? error: ?? ????return?err; ?? } ?? ?? static?__exit?void?simple_exit(void) ?? { ?? ????dev_t?dev; ?? #if?SIMPLE_DEBUG??? ????printk(KERN_INFO?"In?%s\n",?__func__); ?? #endif??? ????dev?=?MKDEV(simple_major,?simple_minor); ?? ????unregister_chrdev_region(dev,?DEV_COUNT);?//釋放設備號?? } ?? ?? module_init(simple_init); ?? module_exit(simple_exit); ?? ?? MODULE_LICENSE("GPL"); ?? MODULE_AUTHOR("kai_zhang(jsha.zk@163.com)"); ?? MODULE_DESCRIPTION("simple?char?driver!");??
主設備號標識設備連接的的驅動,此設備好由內核使用,標識在相應驅動下得對應的設備
在linux中設備號是一個32位的dev_t類型
typedef?__u32????__kernel_dev_t;
typedef?__kernel_dev_t????dev_t;
crw-------?1?root??root??10,?1?Apr?11??2011?psaux?
crw-------?1?root??root??4,??1?Oct?2803:04?tty1?
crw-rw-rw-?1?root??tty???4,?64?Apr?11??2011?ttys0?
crw-rw----?1?root??uucp??4,?65?Apr?11??2011?ttyS 上圖是再/dev目錄下用$ls -l 命令顯示的部分結果可以看到tty driver的主設備號都為4(各個系統版本有差別),次設備號不同
| 前12位標識主設備號 | MAJOR(dev_t dev) | 獲得主設備號 |
| 后20位標識此設備號 | MINOR(dev_t dev) | 獲得此設備號 |
由主次設備號生成設備號
可以使用宏MKDEV
dev_t ?dev_num = MKDEV(dev_t major, dev_t minor);
2、分配與釋放設備號
在linux2.6的字符設備中(kernel3.0也是)首先做的事就是申請一個或者多個設備號
靜態分配設備號,是在已經知道一個可用設備號的時候使用,而程序員在編寫程序之前大多并知道設備號是否可用,或者現在可用,不能確保在系統升級時候次設備還是可用的
所以linux社區極力推薦使用動態分配,它會去尋找可用的設備號,而不會產生沖突。在次設備卸載的時候需要釋放次設備號。
3、一個沒有作用的字符設備驅動
這里只在模塊初始化的時候去分配設備號,在模塊注銷的時候去釋放次驅動擁有的設備號
在函數里邊我們看到用到了在應用編程里邊聲名狼藉的goto函數,在linux驅動編程時 goto 函數可以讓我們的編程更加有條理性,在出現錯誤時候能更快的去處理。
如果在調用函數檢查返回者都去做錯誤處理則模塊函數就顯得臃腫,龐大。所以還是建議合理使用goto函數的。
加載次模塊后?
運行 $cat /proc/devices可以看到?simple_char 的設備以及主設備號。
這里我們看到原來假設的主設備號是不可用的,所以使用的動態分配設備號,由此我們申請到主設備號為249,我們可以在上邊添加我們的設備,具體操作下一節會講到。呵呵留點懸念先。
總結
以上是生活随笔為你收集整理的Linux驱动编程 step-by-step (二) 简单字符设备驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux驱动编程 step-by-st
- 下一篇: Linux驱动编程 step-by-st