歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

【Linux 驅動】驅動開發第一步----開發環境搭配

一,環境搭建步驟

1)下載Linux源碼
1> ~#apt-cache search linux-source
出現:linux-source - Linux kernel source with Ubuntu patches
linux-source-3.0.0 - Linux kernel source for version 3.0.0 with Ubuntu patches
2>~#apt-get   install linux-source-3.0.0
下載完成後,在/usr/src/下會出現一個linux-source-3.0.0.tar.bz2。解壓:      tar  jxvf   linux-source-3.0.0.tar.bz2
3>然後在Linux內核源碼目錄/usr/src/linux-source-2.6.32目錄下面用老的方法配置好Linux內核:
~#make oldconfig
4>編譯內核:~#make     //大概需要一個小時
5>編譯模塊:~#make modules
6>安裝模塊:~#make modules_install

以上步驟完成後,會在/lib/modules 目錄下生成一個文件夾3.0.0-12-generic

二,hello.c

  1. #include <linux/init.h>  
  2. #include <linux/module.h>  
  3. MODULE_LICENSE("Dual BSD/GPL");  
  4.   
  5. static int hello_init(void)  
  6. {  
  7.    printk(KERN_ALERT "Hello, world\n");  //printk 跟printf 類似,只是printk運行在內核態  
  8.    return 0;  
  9. }  
  10. static void hello_exit(void)  
  11. {  
  12.    printk(KERN_ALERT "Goodbye, cruel world\n");  
  13. }  
  14.   
  15. module_init(hello_init);  
  16. module_exit(hello_exit);  

三,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. endif   
四,~#make   //生成文件如下

hello.c   hello.ko     hello.mod.o  Makefile   modules.order
hello.c~  hello.mod.c  hello.o      Makefile~  Module.symvers

1>裝載目標模塊:~#insmod  ./hello.ko

     ~#lsmod  //查看目前安裝的驅動模塊,有hello

2>模塊裝載觸發hello.c的init()方法,輸出hello world,如果沒有的話,是因為其將輸出放到/var/log/syslog中去了。打開便可以看見你的結果!

卸載目標模塊命令是:~#rmmod ./hello.ko


 總結:從此我們邁出了Linux驅動開發的第一步


代碼深度解析:

1)查找文件位置:

  1. #include <linux/init.h>//這個頭文件包含了你的模塊初始化與清除的函數  
  2. #include <linux/module.h>//包含了許多符號與函數的定義,這些符號與函數多與加載模塊有關  
     find / -name  module.h

     我的文件位置在:/usr/src/linux-source-3.0.0/include/linux/module.h   //其余的位置也有好多,但是這個文件位置才是正解

                                    /usr/src/linux-source-3.0.0/include/linux/in.h

2)另外,如果你的模塊需要用到參數傳遞,那麼你可能就要聲明moduleparam.h這個頭文件了。

3)模塊裡常包含一些描述性聲明,如:

MODULE_LICENSE("GPL");          // "GPL" 是指明了 這是GNU General Public License的任意版本

                                                            // “GPL v2” 是指明 這僅聲明為GPL的第二版本

                                                            // "GPL and addtional"

                                                            // "Dual BSD/GPL"

                                                            // "Dual MPL/GPL"

                                                            // "Proprietary"  私有的

                                                            // 除非你的模塊顯式地聲明一個開源版本,否則內核會默認你這是一個私有的模塊(Proprietary)。

MODULE_AUTHOR                        // 聲明作者

MODULE_DESCRIPTION              // 對這個模塊作一個簡單的描述,這個描述是"human-readable"的

MODULE_VERSION                        // 這個模塊的版本

MODULE_ALIAS                               // 這個模塊的別名

MODULE_DEVICE_TABLE            // 告訴用戶空間這個模塊支持什麼樣的設備


       MODULE_聲明可以寫在模塊的任何地方(但必須在函數外面),但是慣例是寫在模塊最後。

4)

Linux KERN_ALERT 什麼意思

消息打印級別:
fmt----消息級別:

#define KERN_EMERG     "<0>"
#define KERN_ALERT     "<1>"
#define KERN_CRIT      "<2>"
#define KERN_ERR       "<3>"
#define KERN_WARNING   "<4>"
#define KERN_NOTICE    "<5>"
#define KERN_INFO      "<6>"
#define KERN_DEBUG     "<7>"

 不同級別使用不同字符串表示,數字越小,級別越高。
printk輸出跟輸出的日志級別有關系,當輸出日志級別比控制台的級別高時,就會顯示在控制台上,當比控制台低時,則會記錄在/var/log/message中.但是當系統同時運行了klogd和syslogd時,都追加到/var/log/message.在/proc/sys/kernel/printk文件中,前兩個整數為當前的日志級別和默認的日志級別(默認的日志級別即為printk的輸出級別). 

注意:
需要開啟klogd和syslogd服務才能正常輸出。通過klogd可以改變系統消息輸出級別。

 linux0.11為什麼在內核態使用printk()函數,而在用戶態使用printf()函數?
(1)    答:printk()函數是直接使用了向終端寫函數tty_write()。而printf()函數是調用write()系統調用函數向標准輸出設備寫。所以在用戶態(如進程0)不能夠直接使用printk()函數,而在內核態由於他已是特權級,所以無需系統調用來改變特權級,因而能夠直接使用printk()函數。

printk是內核輸出,在終端是看不見的。  
  你可以看一下系統日志。/var/log/message。  
  或者使用dmesg命令看一下

不管你可能怎麼想,printk()並不是設計用來同用戶交互的,雖然我們在 hello-1就是出於這樣的目的使用它!它實際上是為內核提供日志功能, 記錄內核信息或用來給出警告。因此,每個printk() 聲明都會帶一個優先級,就像你看到的<1>KERN_ALERT 那樣。內核總共定義了八個優先級的宏, 所以你不必使用晦澀的數字代碼,並且你可以從文件linux/kernel.h查看這些宏和它們的意義。如果你 不指明優先級,默認的優先級DEFAULT_MESSAGE_LOGLEVEL將被采用。

閱讀一下這些優先級的宏。頭文件同時也描述了每個優先級的意義。在實際中, 使用宏而不要使用數字,就像<4>。總是使用宏,就像 KERN_WARNING

當優先級低於int console_loglevel,信息將直接打印在你的終端上。如果同時 syslogd和klogd都在運行,信息也同時添加在文件 /var/log/messages,而不管是否顯示在控制台上與否。我們使用像 KERN_ALERT這樣的高優先級,來確保printk()將信息輸出到 控制台而不是只是添加到日志文件中。 當你編寫真正的實用的模塊時,你應該針對可能遇到的情況使用合 適的優先級。

相關閱讀:

【Linux 驅動】第一章 設備驅動程序簡介  http://www.linuxidc.com/Linux/2012-04/58410.htm

【Linux 驅動】第二章 構造和運行模塊  http://www.linuxidc.com/Linux/2012-04/58411.htm

Copyright © Linux教程網 All Rights Reserved