成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux驅(qū)動(dòng)實(shí)踐:帶你一步一步編譯內(nèi)核驅(qū)動(dòng)程序

系統(tǒng) Linux
今天給大家分享一些筆記本里的一些存貨: Linux 系統(tǒng)中的驅(qū)動(dòng)和中斷相關(guān)。在這部分,會(huì)以 GPIO 為例子,重點(diǎn)描述其中的關(guān)鍵節(jié)點(diǎn)。

[[434709]]

別人的經(jīng)驗(yàn),我們的階梯!

大家好,我是道哥。今天給大家分享一些筆記本里的一些存貨: Linux 系統(tǒng)中的驅(qū)動(dòng)和中斷相關(guān)。

大概會(huì)用 6~7 篇的文章,由淺入深的為大家介紹Linux 中驅(qū)動(dòng)程序的編寫方法。

文章的順序,也是我之前自己學(xué)習(xí)時(shí)的順序。

以前的學(xué)習(xí)記錄比較零散,現(xiàn)在只是把它們按照一定的順序重新梳理一下。

這幾篇文章,理論知識(shí)會(huì)少一些,更注重實(shí)際的操作。

我會(huì)把操作用引導(dǎo)的代碼,全部上傳到網(wǎng)盤上,在文末有下載說明。

只要根據(jù)文中介紹的步驟進(jìn)行操作,就一定可以操作成功。

學(xué)習(xí)的困惑

記得以前我在開始學(xué)習(xí)驅(qū)動(dòng)開發(fā)的時(shí)候,找來很多文章、資料來學(xué)習(xí),但是總是覺得缺少了點(diǎn)全局視角。

就好像:我想看清一座山的全貌,但總是被困在一個(gè)、又一個(gè)山谷中一樣。

主要的困惑有 3 點(diǎn):

  1. 每一篇文章的介紹都是正確的,但是如果把很多文章放在一起看,就會(huì)發(fā)現(xiàn)怎么說的都不一樣啊?
  2. 有些文章注重函數(shù)的介紹,但是缺乏一個(gè)全局的視角,從整體上來觀察驅(qū)動(dòng)程序的結(jié)構(gòu);
  3. 對(duì)于一個(gè)新手來說,能夠邊學(xué)習(xí)、邊實(shí)踐,這是最好的學(xué)習(xí)方式,但是很多文章不會(huì)注意這方面。雖然文章內(nèi)容很漂亮,但是不知道怎么去實(shí)踐、驗(yàn)證。

因此,這幾篇文章我們就從最簡(jiǎn)單的驅(qū)動(dòng)模塊編譯開始,然后介紹字符設(shè)備驅(qū)動(dòng)程序。

在這部分,會(huì)以 GPIO 為例子,重點(diǎn)描述其中的關(guān)鍵節(jié)點(diǎn)。

最后再介紹在中斷處理程序中,如何利用信號(hào)量、小任務(wù)、工作隊(duì)列,把內(nèi)核事件傳遞到應(yīng)用層來處理。

作為第一個(gè)開篇文章,從最簡(jiǎn)單的內(nèi)核編譯開始。

實(shí)際操作一下:如何把一個(gè)最簡(jiǎn)單的驅(qū)動(dòng)程序(hello),按照 2 種方式進(jìn)行編譯:

  1. 編譯進(jìn)內(nèi)核;
  2. 編譯為一個(gè)獨(dú)立的驅(qū)動(dòng)模塊;

實(shí)踐環(huán)境

為了便于測(cè)試,以下操作都是在 Ubuntu16.04 操作系統(tǒng)里完成的。

編譯Linux驅(qū)動(dòng)程序,肯定需要內(nèi)核源碼,這里選擇的是 linux-4.15 版本,可以在官網(wǎng)下載。

文末有下載方式。

下載之后,把linux-4.15.tar.gz解壓到Ubuntu中任意目錄即可,例如:解壓到~/tmp/目錄下:

  1. $ tar -zxvf linux-4.15.tar.gz -C ~/tmp/ 

編譯進(jìn)內(nèi)核

創(chuàng)建驅(qū)動(dòng)程序目錄

linux 中的驅(qū)動(dòng),一般都放在 linux-4.15/drivers/ 目錄下,因此在這個(gè)目錄中創(chuàng)建一個(gè)hello文件夾。

  1. $ mkdir linux-4.15/drivers/hello 

對(duì)于一個(gè)驅(qū)動(dòng)來說,最重要的就是3個(gè)文件:

  1. 源代碼
  2. Kconfig
  3. Makefile

只要按照固定的格式來編寫這3個(gè)文件,linux內(nèi)核的編譯腳本就可以確保把我們的驅(qū)動(dòng)程序編譯進(jìn)去。

創(chuàng)建源文件

首先是源碼,在hello文件夾中創(chuàng)建源文件 hello.c:

  1. $ cd linux-4.15/drivers/hello 
  2. $ touch hello.c 

源文件hello.c的內(nèi)容是:

  1. #include <linux/module.h> 
  2. #include <linux/init.h> 
  3.  
  4. // 當(dāng)驅(qū)動(dòng)被加載的時(shí)候,執(zhí)行此函數(shù) 
  5. static int __init hello_init(void) 
  6.     printk(KERN_ALERT "welcome, hello"\n"); 
  7.     return 0; 
  8.  
  9. // 當(dāng)驅(qū)動(dòng)被卸載的時(shí)候,執(zhí)行此函數(shù) 
  10. static void __exit hello_exit(void) 
  11.     printk(KERN_ALERT "bye, hello\n"); 
  12.  
  13. // 版權(quán)聲明 
  14. MODULE_LICENSE("GPL"); 
  15.  
  16. // 以下兩個(gè)函數(shù)屬于 Linux 的驅(qū)動(dòng)框架,只要把驅(qū)動(dòng)兩個(gè)函數(shù)地址注冊(cè)進(jìn)去即可。 
  17. module_init(hello_init); 
  18. module_exit(hello_exit); 

有兩個(gè)小地方注意一下:

  1. 在內(nèi)核中,打印函數(shù)是 printk,而不是 printf;
  2. 打印信息的級(jí)別有好幾個(gè),從 DEBUG 到 EMERG,這里使用的是 KERN_ALERT,方便查看打印信息。

創(chuàng)建 Kconfig 文件

這個(gè)文件是用來對(duì)內(nèi)核進(jìn)行配置的,當(dāng)執(zhí)行 make menuconfig 指令的時(shí)候,這個(gè)文件就被解析。

先創(chuàng)建文件:

  1. $ cd linux-4.15/drivers/hello 
  2. $ touch Kconfig 

添加如下內(nèi)容:

  1. config HELLO 
  2. tristate "hello driver" 
  3. help 
  4.   just a simplest driver. 
  5. default y 

第一行內(nèi)容 config HELLO ,在執(zhí)行配置的時(shí)候,將會(huì)生成一個(gè)變量 CONFIG_HELLO ,而這個(gè)變量,將會(huì)在編譯的時(shí)候,被 Makefile 引用。

最后一行的 default y ,就表示把 CONFIG_HELLO 的值設(shè)置成 y,從而讓這個(gè)驅(qū)動(dòng)被編譯到內(nèi)核中。

現(xiàn)在,hello驅(qū)動(dòng)中的KConfig配置文件已經(jīng)準(zhǔn)備好了,但是還需要這個(gè)配置文件登記到 Linux 內(nèi)核的整體配置文件中。

也就是把它登記在 linux-4.15/drivers/Kconfig 文件的末尾:

  1. source "drivers/hello/Kconfig" 
  2.  
  3. endmenu   // 加在這一句的上面 

現(xiàn)在,可以來執(zhí)行下面指令,看一下具體的配置界面:

  1. $ cd linux-4.15/ 
  2. $ make distclean 
  3. $ make ARCH=x86_64 defconfig 
  4. $ make ARCH=x86_64 menuconfig 

第2條指令,是用來把默認(rèn)的配置保存到當(dāng)前目錄下的 .config 配置文件,也就是把一個(gè)默認(rèn)的配置文件復(fù)制過來,作為我們自己的配置文件。

以后再修改配置參數(shù)時(shí),修改的內(nèi)容就會(huì)存儲(chǔ)在 .config 文件中,

第3條指令,是用來配置內(nèi)核的,可以進(jìn)入 Device Drivers 菜單,然后在最底層看到我們的 hello driver 被標(biāo)記成星號(hào), 這表示被編譯進(jìn)內(nèi)核。

按向下方向鍵,把高亮定位到 Device Drivers ---> ,然后敲回車鍵,進(jìn)入到 Device Drivers 的配置界面。

按向下方向鍵,一直到最后一個(gè)條目,就可以看到我們的 hello 驅(qū)動(dòng)了,如下:

可以看到 hello driver 前面顯示的是型號(hào) *,這表示:該驅(qū)動(dòng)將會(huì)編譯進(jìn)內(nèi)核。

我們可以按下空格鍵試一下,會(huì)在三種標(biāo)記中切換:型號(hào),M,空值。M 標(biāo)記意思是編譯成驅(qū)動(dòng)模塊。

我們這里選擇星號(hào)(編譯進(jìn)內(nèi)核),然后按下右方向鍵,最下方的幾個(gè)按鍵的焦點(diǎn)移動(dòng)到按鈕上:

按下回車鍵,就會(huì)彈出保存對(duì)話框,選擇默認(rèn)保存文件 .config 即可,然后在按鈕高亮的時(shí)候,按下回車鍵即可保存。

此時(shí),在彈出的確認(rèn)窗口中,選擇 ,按下回車鍵即可:

此時(shí),返回到 Device Drivers 的配置界面,在最下面的按鈕中,選擇讓 高亮,然后一路退出即可。

創(chuàng)建 Makefile 文件

Makefile 文件是make工具的腳本,首先創(chuàng)建它:

  1. $ cd linux-4.15/drivers/hello 
  2. $ touch Makefile 

其中的內(nèi)容只有一行:

  1. obj-$(CONFIG_HELLO) += hello.o 
  1. CONFIG_HELLO 可以看做一個(gè)變量,在編譯的時(shí)候,這個(gè)變量的值可能是:y, n 或者 m。
  2. 在剛才的 Kconfig 參數(shù)配置中,CONFIG_HELLO 被設(shè)置為 y,于是這句話就被翻譯成:obj-y += hello,表示把 hello 驅(qū)動(dòng)編譯進(jìn)內(nèi)核。

現(xiàn)在,hello驅(qū)動(dòng)程序的Makefile已經(jīng)創(chuàng)建好了,我們還要讓linux內(nèi)核的編譯框架知道這個(gè)文件才行。

在文件 linux-4.15/drivers/Makefile 中的末尾,添加如下內(nèi)容:

  1. obj-$(CONFIG_HELLO)    += hello/ 

編譯

萬事俱備,只欠編譯!依次執(zhí)行如下指令:

  1. $ cd linux-4.15/ 
  2. $ make -j4 

make指令執(zhí)行結(jié)束之后,編譯得到的內(nèi)核中(vmlinux)就包含了我們的hello驅(qū)動(dòng)。

編譯為驅(qū)動(dòng)模塊

編譯為驅(qū)動(dòng)模塊,也有兩種 操作方式:

編譯所有的驅(qū)動(dòng)模塊

  1. 在執(zhí)行 make ARCH=x86_64 menuconfig 指令的時(shí)候,把 hello 配置成 M;
  2. 然后在 linux-4.15 中執(zhí)行編譯模塊指令:make -j4 modules。

編譯成功之后,就可以得到文件: linux-4.15/drivers/hello/hello.ko。

這樣的編譯指令,是把所有的模塊都編譯了一次(在輸出信息中,可以看到編譯了很多模塊)。

只編譯 hello 這一個(gè)驅(qū)動(dòng)模塊

另外一種編譯驅(qū)動(dòng)模塊的方式是:進(jìn)入hello目錄,只編譯這一個(gè)驅(qū)動(dòng)模塊。

這種編譯方法,就需要修改hello目錄下的Makefile文件了,內(nèi)容如下:

可以把 hello 目錄下的所有文件刪除,只保留源文件 hello.c,然后新建 Makefile 文件。

  1. ifneq ($(KERNELRELEASE),) 
  2.         obj-m := hello.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 

然后,在hello文件夾中執(zhí)行make指令,即可得到驅(qū)動(dòng)模塊 hello.ko 。

驗(yàn)證一下

加載驅(qū)動(dòng):

  1. $ cd linux-4.15/drivers/hello 
  2. $ sudo insmod ./hello.ko 

此時(shí)終端窗口是沒有任何輸出的,需要輸入指令 dmesg | tail ,可以看到 hello_init 函數(shù)的輸出內(nèi)容:

卸載驅(qū)動(dòng):

  1. $ sudo rmmod hello 

再次輸入 dmesg | tail ,可以看到 hello_exit 函數(shù)的輸出內(nèi)容:

本文轉(zhuǎn)載自微信公眾號(hào)「IOT物聯(lián)網(wǎng)小鎮(zhèn)」

 

責(zé)任編輯:姜華 來源: IOT物聯(lián)網(wǎng)小鎮(zhèn)
相關(guān)推薦

2021-11-22 08:14:23

Linux Linux驅(qū)動(dòng)Linux 系統(tǒng)

2019-03-05 14:09:27

Docker存儲(chǔ)容器

2019-07-09 15:23:22

Docker存儲(chǔ)驅(qū)動(dòng)

2018-12-24 10:04:06

Docker存儲(chǔ)驅(qū)動(dòng)

2019-11-04 10:06:19

MySQL索引

2022-08-29 15:19:09

CSS煙花動(dòng)畫

2009-07-06 19:29:37

云計(jì)算私有云服務(wù)器虛擬化

2010-07-12 17:10:23

Android應(yīng)用程序

2017-09-13 09:05:29

iOS11iOS蘋果

2015-05-25 09:51:55

Azure混合云平臺(tái)VPN技術(shù)

2019-09-18 07:20:34

深度學(xué)習(xí)人臉識(shí)別人工智能

2011-06-07 16:03:48

匿名SQL Server

2018-03-07 15:24:41

PythonMySQL

2013-03-18 16:09:27

JavaEEOpenfire

2013-11-11 13:24:21

cocos2dx 2.Android編譯

2009-12-18 16:27:43

Cisco路由器配置

2012-03-22 10:33:33

思杰XenDesktop

2022-09-30 15:37:19

Web網(wǎng)站服務(wù)器

2017-09-28 09:40:36

圖像分類準(zhǔn)確率

2017-08-24 08:31:41

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人在线一区二区 | 在线观看av不卡 | 国产99视频精品免费播放照片 | 欧美第一页 | 欧美不卡视频一区发布 | 久久综合一区 | 91麻豆产精品久久久久久 | 久久成人人人人精品欧 | 一级美国黄色片 | 欧美一级片免费看 | 牛牛热在线视频 | 91精品国产综合久久久久久丝袜 | 久久精品一区二区三区四区 | 欧美激情一区二区三区 | 午夜爽爽男女免费观看hd | 久久久久久免费精品一区二区三区 | 免费在线观看av网站 | 午夜av一区二区 | 中文字幕一区二区三区不卡 | 97国产精品视频 | 成人精品鲁一区一区二区 | 五月天婷婷综合 | 日韩精品激情 | 亚洲欧美一区二区三区国产精品 | 国产成人精品a视频一区www | 色屁屁在线观看 | 性一交一乱一伦视频免费观看 | 国产精品欧美日韩 | 中文字幕亚洲一区二区va在线 | 国产亚洲精品精品国产亚洲综合 | 亚洲欧美日韩中文在线 | 欧美片网站免费 | 欧洲尺码日本国产精品 | 国产成人精品一区二三区在线观看 | 精品日韩一区 | 99视频在线 | 337p日本欧洲亚洲大胆鲁鲁 | 在线久草| av激情在线 | 亚洲人成在线观看 | 亚洲精品第一国产综合野 |