精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Linux驅動實踐:一步一步編寫字符設備驅動程序

系統 Linux
字符設備的驅動程序,有兩套不同的API函數,并且在文中詳細演示了利用舊的API函數來編寫驅動程序。這篇文章,我們繼續這個話題,實際演示一下:字符設備驅動程序的另一套API函數的使用方法。

[[436073]]

別人的經驗,我們的階梯!

大家好,我是道哥,今天我們繼續討論: Linux 中字符設備的驅動程序。

在上一篇文章中Linux驅動實踐:你知道【字符設備驅動程序】的兩種寫法嗎?我們說過:字符設備的驅動程序,有兩套不同的API函數,并且在文中詳細演示了利用舊的API函數來編寫驅動程序。

這篇文章,我們繼續這個話題,實際演示一下:字符設備驅動程序的另一套API函數的使用方法。

API 函數

這里主要關注下面這 3 個函數:

  1. // 靜態注冊設備 
  2. int register_chrdev_region(dev_t from, unsigned count, const char *name); 
  3.  
  4. // 動態注冊設備 
  5. int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name); 
  6.  
  7. // 卸載設備 
  8. void unregister_chrdev_region(dev_t from, unsigned count); 

關于靜態和動態注冊,主要的區別就在于:主設備號由誰來主導分配!

靜態注冊:由我們的驅動程序來指定主設備號,即參數1:from;

動態注冊:由操作系統來分配,驅動程序提供一個變量來接收該設備號,即參數1: dev 指針;

另外,在Linux 2.6后期的內核版本中,引入了 cdev 結構來描述一個字符設備,它的結構體成員是:

  1. struct cdev { 
  2.     struct kobject kobj;    // 內嵌的kobject對象 
  3.     struct module *owner;   // 所屬模塊 
  4.     const struct file_operations *ops;//文件操作結構體 
  5.     struct list_head list;  // 鏈表句柄 
  6.     dev_t dev;              // 設備號 
  7.     unsigned int count
  8. }; 

與這個結構體相關的處理函數有:

  • void cdev_init(struct cdev *,struct file_operations *);
  • 初始化 cdev 的成員,主要是設置 file_operations。
  • strcut cdev *cdev_alloc(void);
  • 動態申請 cdev 內存。
  • void cdev_put(strcut cdev *p);
  • 與 count 計數相關的操作。
  • int cdev_add(struct cdev *,dev_t ,unsigned );
  • 向系統中添加一個 cdev,注冊字符設備,需要在驅動被加載的時候調用。
  • void cdev_del(struct cdev *);
  • 從系統中刪除一個 cdev,注銷字符設備,需要在驅動被卸載的時候調用。
  • 后面在代碼演示的時候,可以看到cdev結構是如何被使用的。

編寫驅動

按照慣例,我們仍然按照步驟,來討論如何利用上述的APIs,來手寫一個字符設備的驅動程序。

以下所有操作的工作目錄,都是與上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。

創建驅動目錄和驅動程序

  1. $ cd linux-4.15/drivers/ 
  2. $ mkdir my_driver2 
  3. $ cd my_driver2 
  4. $ touch driver2.c 

driver2.c 文件的內容如下(不需要手敲,文末有代碼下載鏈接):

  1. #include <linux/module.h> 
  2. #include <linux/kernel.h> 
  3. #include <linux/ctype.h> 
  4. #include <linux/device.h> 
  5. #include <linux/cdev.h> 
  6.  
  7. static struct cdev my_cdev; 
  8. static dev_t dev_no; 
  9.  
  10. int driver2_open(struct inode *inode, struct file *file) 
  11.     printk("driver2_open is called. \n"); 
  12.     return 0; 
  13.  
  14. ssize_t driver2_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) 
  15.     printk("driver2_read is called. \n"); 
  16.     return 0; 
  17.  
  18. ssize_t driver2_write (struct file *file, const char __user *buf, size_t size, loff_t *ppos) 
  19.     printk("driver2_write is called. \n"); 
  20.     return 0; 
  21.   
  22. static const struct file_operations driver2_ops={ 
  23.     .owner = THIS_MODULE, 
  24.     .open  = driver2_open, 
  25.     .read  = driver2_read, 
  26.     .write = driver2_write, 
  27. }; 
  28.   
  29. static int __init driver2_init(void) 
  30.     printk("driver2_init is called. \n"); 
  31.  
  32.     // 初始化cdev結構 
  33.     cdev_init(&my_cdev, &driver2_ops); 
  34.  
  35.     // 注冊字符設備 
  36.     alloc_chrdev_region(&dev_no, 0, 2, "driver2"); 
  37.     cdev_add(&my_cdev, dev_no, 2); 
  38.  
  39.     return 0; 
  40.   
  41. static void __exit driver2_exit(void) 
  42.     printk("driver2_exit is called. \n"); 
  43.  
  44.     // 注銷設備 
  45.     cdev_del(&my_cdev);  
  46.  
  47.     // 注銷設備號 
  48.     unregister_chrdev_region(dev_no, 2); 
  49.   
  50. MODULE_LICENSE("GPL"); 
  51. module_init(driver2_init); 
  52. module_exit(driver2_exit); 

這里看一下加載驅動模塊時調用的 driver2_init( ) 函數,其中的 cdev_init 用來把cdev結構體與 file_operations 發生關聯。

在調用 alloc_chrdev_region( ) 時,操作系統分配了主設備號,并且保存在 dev_no 變量中,然后 cdev_add() 再把設備號與cdev結構體進行關聯。

創建 Makefile 文件

  1. $ touch Makefile 

內容如下:

  1. ifneq ($(KERNELRELEASE),) 
  2.     obj-m := driver2.o 
  3. else 
  4.     KERNELDIR ?= /lib/modules/$(shell uname -r)/build 
  5.     PWD := $(shell pwd) 
  6. default
  7.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
  8. clean: 
  9.     $(MAKE) -C $(KERNEL_PATH) M=$(PWD) clean 
  10. endif 

編譯驅動模塊

  1. $ make 

得到驅動程序: driver2.ko 。

加載驅動模塊

在加載驅動模塊之前,先來檢查一下系統中,幾個與驅動設備相關的地方。

先看一下 /dev 目錄下,目前還沒有我們的設備節點( /dev/driver2 )。

  1. $ ll /dev/driver2 
  2. ls: cannot access '/dev/driver2'No such file or directory 

再來查看一下 /proc/devices 目錄下,也沒有 driver2 設備的設備號。

  1. $ cat /proc/devices 

 

/proc/devices 文件: 列出字符和塊設備的主設備號,以及分配到這些設備號的設備名稱。

為了方便查看打印信息,把dmesg輸出信息清理一下:

  1. $ sudo dmesg -c 

執行如下指令,加載驅動模塊:

  1. $ sudo insmod driver2.ko 

當驅動程序被加載的時候,通過 module_init( ) 注冊的函數 driver2_init() 將會被執行,那么其中的打印信息就會輸出。

還是通過 dmesg 指令來查看驅動模塊的打印信息:

  1. $ dmesg 

此時,驅動模塊已經被加載了!

來查看一下 /proc/devices 目錄下顯示的設備號:

  1. $ cat /proc/devices 

設備已經注冊了,主設備號是: 244 。

但是,此時在/dev目錄下,還沒有我們需要的設備節點。

在上一篇文章中介紹過,還可以利用 Linux 用戶態的 udev 服務來自動創建設備節點。

現在,我們手動創建設備節點:

  1. $ sudo mknod -m 660 /dev/driver2 c 244 0 

主設備號 244 是從 /proc/devices 查到的。

檢查一下是否創建成功:

  1. $ ll /dev/driver2 

現在,設備的驅動程序已經加載了,設備節點也被創建好了,應用程序就可以來操作(讀、寫)這個設備了。

應用程序

應用程序仍然放在 ~/tmp/App/ 目錄下。

  1. $ mkdir ~/tmp/App/app_driver2 
  2. $ cd ~/tmp/App/app_driver2 
  3. $ touch app_driver2.c 

文件內容如下:

  1. #include <stdio.h> 
  2. #include <unistd.h> 
  3. #include <fcntl.h> 
  4.  
  5.  
  6. int main(void) 
  7.     int ret; 
  8.     int read_data[4] = { 0 }; 
  9.     int write_data[4] = {1, 2, 3, 4}; 
  10.     int fd = open("/dev/driver2", O_RDWR); 
  11.     if (-1 != fd) 
  12.     { 
  13.         ret = read(fd, read_data, 4); 
  14.         printf("read ret = %d \n", ret); 
  15.  
  16.         ret = write(fd, write_data, 4); 
  17.         printf("write ret = %d \n", ret); 
  18.     } 
  19.     else 
  20.     { 
  21.         printf("open /dev/driver2 failed! \n"); 
  22.     } 
  23.  
  24.     return 0; 

接下來就是編譯和測試了:

  1. $ gcc app_driver2.c -o app_driver2 
  2. $  
  3. $ sudo ./app_driver2  
  4. [sudo] password for xxx: <輸入用戶密碼> 
  5. read ret = 0  
  6. write ret = 0 

從返回值來看,成功打開了設備,并且調用讀函數、寫函數都成功了!

繼續用dmesg命令查看一下:

卸載驅動模塊

卸載指令:

  1. $ sudo rmmod driver2 

此時,/proc/devices 下主設備號 244 的 driver2 已經不存在了。

再來看一下 dmesg的打印信息:

可以看到:驅動程序中的 driver2_exit( ) 被調用執行了!

小結

以上就是利用“新的” API 函數,來編寫字符設備的驅動程序。

代碼結構還是非常清晰的,這得益于Linux良好的驅動程序架構設計!這也是每一名架構師需要學習、努力模仿的地方。

本文轉載自微信公眾號「IOT物聯網小鎮」

 

責任編輯:姜華 來源: IOT物聯網小鎮
相關推薦

2021-11-12 11:28:01

Linux 內核驅動Linux 系統

2019-07-09 15:23:22

Docker存儲驅動

2019-03-05 14:09:27

Docker存儲容器

2018-12-24 10:04:06

Docker存儲驅動

2021-11-29 07:55:45

Linux GPIO Linux 系統

2022-08-29 15:19:09

CSS煙花動畫

2009-07-06 19:29:37

云計算私有云服務器虛擬化

2011-01-10 18:21:38

linux編寫程序

2010-07-12 17:10:23

Android應用程序

2011-06-07 16:03:48

匿名SQL Server

2018-03-07 15:24:41

PythonMySQL

2013-03-18 16:09:27

JavaEEOpenfire

2009-12-18 16:27:43

Cisco路由器配置

2012-03-22 10:33:33

思杰XenDesktop

2017-09-28 09:40:36

圖像分類準確率

2022-09-30 15:37:19

Web網站服務器

2009-12-17 08:57:28

Windows 7磁盤分區

2024-07-22 11:43:28

LVMPnetLab網絡

2017-08-24 08:31:41

2019-11-04 10:06:19

MySQL索引
點贊
收藏

51CTO技術棧公眾號

国产成人高清视频| 午夜精品电影| 在线观看日韩国产| 正在播放亚洲| 色一情一乱一区二区三区| 一区二区亚洲精品| 亚洲小视频在线| 亚洲理论中文字幕| 最近高清中文在线字幕在线观看1| 久久午夜电影网| 成人日韩在线电影| 国产精品久久久久久久妇| 精品视频久久| 日韩欧美国产精品| 国产性生交xxxxx免费| 成码无人av片在线观看网站| 成人黄色大片在线观看| 国产精品老女人精品视频| 最新日韩免费视频| 日韩美女国产精品| 欧美一区二区三区视频免费| www一区二区www免费| 成人国产免费电影| 国产欧美一区二区在线| av一区二区三区免费| 成人毛片一区二区三区| 在线高清一区| 久久精品在线视频| 亚洲综合欧美综合| 麻豆精品99| 在线播放中文字幕一区| 久久久免费观看| 青娱乐国产视频| 国产精品一线| 欧美一区二区三区四区高清| 能看的毛片网站| 九色porny丨入口在线| 亚洲激情自拍视频| 尤物国产精品| 97人人在线| 久久久久久久精| 国产一区不卡在线观看| 国产a级免费视频| 久久精品国产秦先生| 日本亚洲精品在线观看| 欧美不卡视频在线观看| 黄色一区二区三区四区| 久久精品美女视频网站| 性少妇xx生活| 成人情趣视频网站| 国产视频丨精品|在线观看| 免费看毛片的网站| 亚洲精品aⅴ| 欧美一区二区三区婷婷月色| 免费在线观看污网站| 99只有精品| 欧美三级视频在线| 日韩av片专区| 亚洲日韩中文字幕一区| 欧美日韩一区不卡| 亚洲 国产 图片| 国产精品高清一区二区| 3d动漫精品啪啪| xxww在线观看| 欧美系列精品| 制服丝袜av成人在线看| 奇米影视四色在线| 亚洲伊人伊成久久人综合网| 欧美精品777| 日韩av加勒比| 综合成人在线| 日韩av在线免播放器| 人妻少妇精品视频一区二区三区| 亚洲免费福利一区| 国产一区二区av| 激情无码人妻又粗又大| 亚洲九九视频| 久久久久久噜噜噜久久久精品| 精品无码久久久久| 亚洲免费影视| 国产精品视频一区二区三区四| 亚洲自拍第二页| 国产在线不卡一卡二卡三卡四卡| 91手机视频在线观看| 亚洲精品911| 91丝袜美腿高跟国产极品老师| 欧美精品七区| 成人在线观看亚洲| 亚洲福利国产精品| 熟妇人妻va精品中文字幕| 巨胸喷奶水www久久久免费动漫| 欧美久久久久久久久中文字幕| 日韩av福利在线观看| 欧美日韩黄色| 国产视频精品免费播放| 神马久久精品综合| 亚洲精品三级| 国产日韩亚洲欧美| 色噜噜在线播放| 国产欧美日韩另类一区| 老司机午夜网站| 中国字幕a在线看韩国电影| 欧美日韩一区在线观看| 成人性生活免费看| 五月天久久777| 欧美在线一区二区视频| 国产精品亚洲lv粉色| 9久草视频在线视频精品| 色综合电影网| 欧美巨大丰满猛性社交| 精品污污网站免费看| 亚洲少妇一区二区三区| 欧美综合一区| 国产91ⅴ在线精品免费观看| 国产日韩欧美视频在线观看| 国产亚洲欧洲997久久综合| 国产亚洲精品久久久久久久| 福利一区二区免费视频| 亚洲电影免费观看| 放荡的美妇在线播放| 三级一区在线视频先锋| 国产伦精品一区二区三毛| 一级毛片视频在线| 色狠狠桃花综合| 99久久久无码国产精品性波多| 色综合久久网| 2019av中文字幕| 亚洲国产中文字幕在线| 国产精品剧情在线亚洲| 欧美视频第一区| www.久久东京| 欧美国产精品va在线观看| 国产成人av免费| 久久综合久久久久88| www.亚洲成人网| 麻豆一二三区精品蜜桃| 中文字幕日韩欧美精品在线观看| 综合激情网五月| 成人黄色国产精品网站大全在线免费观看| 在线观看欧美一区| 六九午夜精品视频| 夜夜嗨av色综合久久久综合网| 日本天堂网在线| 99精品一区二区三区| 日韩视频在线视频| 影音先锋欧美激情| 欧美国产日韩二区| 日本精品久久久久| 亚洲国产一区二区a毛片| 香蕉视频色在线观看| 亚洲精品91| av成人午夜| ririsao久久精品一区| 精品国产乱码久久| 国产精品a成v人在线播放| 成人免费视频caoporn| 搞av.com| 无码少妇一区二区三区| 日韩美女免费线视频| 经典三级在线| 欧美天堂一区二区三区| 国产午夜精品理论片在线| 国产综合色在线视频区| 日韩国产精品毛片| 一区二区三区在线免费看| 久久露脸国产精品| 欧美欧美欧美| 欧美日韩国产在线观看| 欧美做爰爽爽爽爽爽爽| 不卡av在线网| 杨幂毛片午夜性生毛片| 婷婷激情综合| 国产亚洲福利社区| 欧美xo影院| 久久久999精品视频| 亚洲国产精品suv| 欧美性生交xxxxxdddd| 纪美影视在线观看电视版使用方法| 精品一区二区三区在线播放视频 | 免费av不卡| 欧美一区二区三区爱爱| 久久久久性色av无码一区二区| 日本成人中文字幕在线视频 | 亚洲免费一级视频| 99精品视频在线观看播放| 成人免费大片黄在线播放| 岛国毛片av在线| 国产丝袜一区二区三区| 亚洲视屏在线观看| 亚洲男人天堂一区| 亚洲国产精品自拍视频| 丝袜a∨在线一区二区三区不卡| 天堂va久久久噜噜噜久久va| 日韩欧美中文字幕一区二区三区| 欧美激情在线观看| 久久av少妇| 欧美高清www午色夜在线视频| 欧美日韩中文字幕在线观看| bt7086福利一区国产| 国产成人亚洲精品无码h在线| 欧美日韩中文字幕一区二区三区| 国产精品一区二区久久国产| 久久一卡二卡| 亚洲区免费影片| 国产喷水吹潮视频www| 天天影视色香欲综合网老头| 久久久久久视频| 91麻豆6部合集magnet| 天天操天天干天天做| 亚洲第一区色| 天堂а√在线中文在线| 国产精品探花在线观看| 亚洲一区二区中文| 奇米777日韩| 国内精品久久影院| 91在线高清| 亚洲国产成人av在线| 亚洲精品久久久久久久蜜桃| 黄色一区二区三区| 亚洲欧洲综合网| 91在线观看视频| www.com污| 青青草91视频| 日本欧美黄色片| 亚洲先锋影音| 视频一区三区| 视频精品在线观看| 丁香五月网久久综合| 91av一区| 日韩av成人在线观看| av资源网在线播放| 久久久国产精彩视频美女艺术照福利| 午夜视频免费在线| 欧美一区二区三区不卡| 国产尤物在线观看| 色婷婷久久99综合精品jk白丝| 欧美日韩免费一区二区| 欧美国产1区2区| 夜夜春很很躁夜夜躁| 成人精品国产福利| 欧美视频亚洲图片| 日本在线不卡视频| 黑人粗进入欧美aaaaa| 国产欧美亚洲一区| 国产日本在线播放| 亚洲国产精品久久久天堂| 99久re热视频精品98| 久久网站免费观看| 五月天国产一区| 国产尤物久久久| 欧美激情导航| 久久99国产成人小视频| 国产一区二区三区四区五区在线 | 小早川怜子久久精品中文字幕| 成人亚洲精品久久久久软件| 制服下的诱惑暮生| 精品一区二区三区影院在线午夜| 五月天婷婷在线观看视频| 捆绑调教一区二区三区| 亚洲成人福利在线| 免费观看30秒视频久久| 亚洲欧美视频二区| 毛片av一区二区三区| 男女视频在线看| 青青草精品视频| 中文字幕亚洲欧洲| 韩国欧美国产1区| 欧美一级免费在线| 国产成人a级片| 制服丝袜在线第一页| 成人精品一区二区三区四区| 又大又长粗又爽又黄少妇视频| 99久久亚洲一区二区三区青草| 欧美大喷水吹潮合集在线观看| 99麻豆久久久国产精品免费| 第一页在线视频| 91理论电影在线观看| 熟女少妇内射日韩亚洲| 国产女主播视频一区二区| 婷婷激情四射网| 一区二区在线观看免费视频播放| 麻豆亚洲av成人无码久久精品| 亚洲国产精品久久久久婷婷884 | av网站在线不卡| 精彩视频一区二区| 精品国产乱码久久久久夜深人妻| 成人免费观看视频| 美女av免费看| 亚洲免费观看在线观看| 国产无遮挡又黄又爽又色| 亚洲综合色自拍一区| 国产日韩久久久| 欧美一区二区三区的| 人人妻人人澡人人爽人人欧美一区| 国产亚洲精品久久久优势| 麻豆视频在线免费观看| 欧美极品在线视频| 久久人体大尺度| 97人摸人人澡人人人超一碰| 亚洲国产合集| 中文字幕色一区二区| 欧美日韩国产成人精品| 日本新janpanese乱熟| 国产精品自拍一区| 在线观看福利片| 一区二区三区免费| 天天天天天天天干| 精品剧情在线观看| 精品欧美不卡一区二区在线观看| 欧美成人午夜剧场免费观看| 桃花岛tv亚洲品质| 亚洲最大的成人网| 欧美日韩激情| 黄页网站在线观看视频| 久久草av在线| 欧美无人区码suv| 国产女主播视频一区二区| 欧美黄色免费看| 91久久精品网| 亚洲国产福利视频| 久久国产天堂福利天堂| 欧美电影免费观看网站| 99电影在线观看| 亚洲国产精品91| 99视频免费播放| 99国产精品国产精品毛片| 久久久久亚洲av片无码| 欧美伊人久久久久久久久影院| 国内爆初菊对白视频| 日韩在线视频线视频免费网站| 五月婷婷久久久| 久久精品91久久久久久再现| 黄色在线免费观看网站| 97超碰人人看人人| 欧美日韩亚洲三区| 亚洲免费av一区| 国产欧美日韩视频一区二区 | 亚洲成人资源网| 国产精品高潮呻吟av| 亚洲视频一区二区| 人人鲁人人莫人人爱精品| 国产伦一区二区三区色一情| 欧美电影《轻佻寡妇》| 欧美日韩中文不卡| 国产欧美视频一区二区| 日韩中文字幕在线观看视频| 日韩av在线看| 黄色视屏在线免费观看| 操一操视频一区| 激情欧美国产欧美| 久久久久久久久久久久国产精品| 1024成人网| 亚洲精品久久久久久久蜜桃| 在线成人激情视频| 精品网站在线| 日本不卡一区| 美女国产一区二区| 91免费在线看片| 精品视频免费在线| 成人在线网址| 91丨九色丨国产在线| 希岛爱理av一区二区三区| 视频在线观看免费高清| 国产精品福利影院| 精品人妻一区二区三区含羞草 | 亚洲欧美偷拍另类| xf在线a精品一区二区视频网站| 成人午夜淫片100集| 亚洲精品福利视频| 在线视频cao| 伊人久久大香线蕉av一区| 精品伊人久久久久7777人| 男女全黄做爰文章| 精品国产3级a| 美女网站在线看| 国产精品对白一区二区三区| 嫩草成人www欧美| 香蕉视频久久久| 91久久线看在观草草青青| 麻豆传媒视频在线| 99高清视频有精品视频| 欧美日韩午夜| 蜜乳av中文字幕| 欧美老人xxxx18| 第一福利在线视频| 欧美中文娱乐网| 蜜桃精品视频在线| 色欲人妻综合网| 亚洲国产成人在线视频| 高清在线视频不卡| 中文字幕中文字幕在线中一区高清 | 在线观看91久久久久久| 黄色日韩网站| 97视频久久久| 国产精品网站一区| 免费国产精品视频| 国产精品福利小视频| 欧美在线亚洲综合一区| 在线观看国产精品一区| 7777精品伊人久久久大香线蕉最新版|