1. 程式人生 > 實用技巧 >01Linux驅動模組01

01Linux驅動模組01

一、驅動基礎

1、什麼是驅動

能夠通過軟體操作硬體的這份程式就是驅動

2、Linux驅動和ARM裸機驅動的區別

  1)Linux裝置驅動工作時依賴於Linux核心, ARM裸機驅動不依賴於Linux核心,可以單獨執行。 
  2)Linux裝置驅動工作的空間在核心空間的【3G~4G】中,驅動中不能有main函數出現,也不能有while(1)的死迴圈, ARM裸機驅動的程式碼都在一個main函式中編寫完成的。 
  3)Linux裝置驅動可以並行執行(核與核之間可以並行執行,單個核時也可以分時複用執行) ARM裸機驅動的程式是在一個while中分時複用執行的 

3、驅動在核心中的位置

------------------------------------------------------------------------------
user(應用層):
	APP         APP    glibc(C標準庫)
	         -----------------------------------------------------
		    shell:
-----------------系統呼叫(swi軟中斷)-------------------------------------------
kernel(核心層):(5大功能)
	1)檔案管理
	2)記憶體管理
	3)程序管理
	4)網路管理:網路協議棧管理(網路的幾個層次,TCP/IP四層、OSI七層)
	5)裝置管理:裝置驅動管理
-----------------------------------------------------------------------------
hardware(硬體層):
	LED、滑鼠、鍵盤、LCD(幀快取)、camera、音效卡
	emmc、U盤、硬碟、dm9000、TRL8211
-----------------------------------------------------------------------------------------------

4、驅動的種類

1)字元裝置驅動:

按照位元組流來訪問,並且只能順序訪問,不能無序訪問的裝置。

2)塊裝置驅動:

按照block(塊 = 512位元組)來訪問,可以順序訪問,也可以無序訪問的裝置。

3)網絡卡裝置驅動:

和網路通訊相關的裝置驅動,沒有裝置檔案,只能通過socket介面來訪問的裝置驅動

5、Linux核心模組

Linux核心模組的三要素:

1)入口: 驅動資源的申請,驅動物件的註冊
2)出口: 驅動資源的釋放,驅動資源的登出
3)許可證: 遵循 GPL 協議

GNU:GNU IS NOT UNIX 一個提倡軟體自由的組織--->理查德·斯托曼提出的
GPL:GNU通用公共許可證 一種協議

C語言為面向過程的語言,C++為面向物件的語言
驅動使用的是C語言程式設計,但要有面向物件的思想和概念

模組的編寫:!!!

 1 #include <linux/init.h>
 2 #include <linux/module.h>
 3 
 4 //入口
 5 static int __init mycdev_init(void)
 6 {
 7     //__init作用:告訴編譯器將mycdev_init這個函式放到.init.text這個段中
 8     return 0;
 9 }
10 
11 //出口
12 static void __exit mycdev_exit(void)
13 {
14     //__exit作用:告訴編譯器將mycdev_exit這個函式放到.exit.text這個段中
16 }
17 
18 module_init(mycdev_init);
19 //告訴核心入口函式的地址是mycdev_init
20 module_exit(mycdev_exit);
21 //告訴核心出口函式的地址是mycdev_exit
22 MODULE_LICENSE("GPL");
23 //許可證
24

系統關鍵字

1、vi -t __ini
   vim ./include/linux/init.h +44
44 #define __init      __section(.init.text) __cold notr                 驅動模組入口段

2、vi -t __exit
   vim ./include/linux/init.h +83
83 #define __exit     __section(.exit.text) __exitused __cold notrace    驅動模組出口段


以"__"開頭的內容,是給編譯器使用的,不需要太過理解,
如 __init、__exit、__FILE__、__func__、__LINE__

static 關鍵字

在模組的入口函式和出口函式中使用了 static 關鍵字進行了修飾

  作用:是為了避免,自己自定義的模組入口出口函式名,與未知的函式名重名,而帶來的重新定義的問題, 函式可以加上 static 關鍵字修飾,經過 static 關鍵字修飾過的函式的連結屬性為內部,從而解決了該問題 

6、測試:

安裝 insmod xxx.ko
檢視 lsmod
解除安裝 rmmod xxx

7、Makefile編寫

  KERNELDIR = /lib/modules/$(shell uname -r)/build/
  #ubuntu核心的路徑
  
  #KERNELDIR = /home/liu/Linux/kernel-3.4.39/
  #開發板核心的路徑

  PWD=$(shell pwd)
  #當前路徑

  NAME ?= demo.c
  #需要編譯的模組名字

  NAMES := $(patsubst %.c,%,$(NAME))
  #擷取字串 xx.c 裡的 .c 之前的內容

  obj-m:=$(NAMES).o
  #需要的依賴檔案

  all:
        	make -C $(KERNELDIR) M=$(PWD) modules

      @# mkae -C $(KERNELDIR)
      @# 進入核心頂層目錄下,讀取目錄下的Makefile檔案,並執行這個Makefile檔案
      @# M=$(PWD) 	指定編譯模組的路徑
      @# modules 	編譯模組的選項
      @# 如:
      @# 		1、cd $(KERNELDIR) 
      @# 		2、mkae M=$(PWD) modules
  clean:
      make -C $(KERNELDIR) M=$(PWD) clean

      @# mkae -C $(KERNELDIR)
      @# 進入核心頂層目錄下,讀取目錄下的Makefile檔案,並執行這個Makefile檔案
      @# M=$(PWD)  指定編譯模組的路徑
      @# clean     清除的選項
      @# 如:
      @# 		1、cd $(KERNELDIR)
      @# 		2、make M=$(PWD) clean
  cp:
      cp $(NAMES).ko ~/nfs/rootfs/