日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux驱动编程 step-by-step (二) 简单字符设备驱动

發布時間:2024/9/21 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(各個系統版本有差別),次設備號不同

前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也是)首先做的事就是申請一個或者多個設備號

  • /*??靜態分配設備號????
  • ?*??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);??
  • 靜態分配設備號,是在已經知道一個可用設備號的時候使用,而程序員在編寫程序之前大多并知道設備號是否可用,或者現在可用,不能確保在系統升級時候次設備還是可用的
    所以linux社區極力推薦使用動態分配,它會去尋找可用的設備號,而不會產生沖突。在次設備卸載的時候需要釋放次設備號。

    3、一個沒有作用的字符設備驅動

  • #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!");??
  • 這里只在模塊初始化的時候去分配設備號,在模塊注銷的時候去釋放次驅動擁有的設備號
    在函數里邊我們看到用到了在應用編程里邊聲名狼藉的goto函數,在linux驅動編程時 goto 函數可以讓我們的編程更加有條理性,在出現錯誤時候能更快的去處理。
    如果在調用函數檢查返回者都去做錯誤處理則模塊函數就顯得臃腫,龐大。所以還是建議合理使用goto函數的。
    加載次模塊后?
    運行 $cat /proc/devices可以看到?simple_char 的設備以及主設備號。

    這里我們看到原來假設的主設備號是不可用的,所以使用的動態分配設備號,由此我們申請到主設備號為249,我們可以在上邊添加我們的設備,具體操作下一節會講到。呵呵留點懸念先。

    總結

    以上是生活随笔為你收集整理的Linux驱动编程 step-by-step (二) 简单字符设备驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。