① 什麼是linux 平台驅動開發
在學習之前一直對驅動開發非常的陌生,感覺有點神秘。不知道驅動開發和普通的程序開發究竟有什麼不同;它的基本框架又是什麼樣的;他的開發環境有什麼特殊的地方;以及怎麼寫編寫一個簡單的字元設備驅動前編譯載入,下面我就對這些問題一個一個的介紹。
一、驅動的基本框架
1. 那麼究竟什麼是驅動程序,它有什麼用呢:
l 驅動是硬體設備與應用程序之間的一個中間軟體層
l 它使得某個特定硬體能夠響應一個定義良好的內部編程介面,同時完全隱蔽了設備的工作細節
l 用戶通過一組與具體設備無關的標准化的調用來完成相應的操作
l 驅動程序的任務就是把這些標准化的系統調用映射到具體設備對於實際硬體的特定操作上
l 驅動程序是內核的一部分,可以使用中斷、DMA等操作
l 驅動程序在用戶態和內核態之間傳遞數據
2. Linux驅動的基本框架
3. Linux下設備驅動程序的一般可以分為以下三類
1) 字元設備
a) 所有能夠象位元組流一樣訪問的設備都通過字元設備來實現
b) 它們被映射為文件系統中的節點,通常在/dev/目錄下面
c) 一般要包含open read write close等系統調用的實現
2) 塊設備
d) 通常是指諸如磁碟、內存、Flash等可以容納文件系統的存儲設備。
e) 塊設備也是通過文件系統來訪問,與字元設備的區別是:內核管理數據的方式不同
f) 它允許象字元設備一樣以位元組流的方式來訪問,也可一次傳遞任意多的位元組。
3) 網路介面設備
g) 通常它指的是硬體設備,但有時也可能是一個軟體設備(如回環介面loopback),它們由內核中網路子系統驅動,負責發送和接收數據包。
h) 它們的數據傳送往往不是面向流的,因此很難將它們映射到一個文件系統的節點上。
二、怎麼搭建一個驅動的開發環境
因為驅動是要編譯進內核,在啟動內核時就會驅動此硬體設備;或者編譯生成一個.o文件, 當應用程序需要時再動態載入進內核空間運行。因此編譯任何一個驅動程序都要鏈接到內核的源碼樹。所以搭建環境的第一步當然是建內核源碼樹
1. 怎麼建內核源碼樹
a) 首先看你的系統有沒有源碼樹,在你的/lib/ moles目錄下會有內核信息,比如我當前的系統里有兩個版本:
#ls /lib/ moles
2.6.15-rc7 2.6.21-1.3194.fc7
查看其源碼位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
發現build是一個鏈接文件,其所對應的目錄就是源碼樹的目錄。但現在這里目標目錄已經是無效的了。所以得自己重新下載
b)下載並編譯源碼樹
有很多網站上可以下載,但官方網址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下載完後當然就是解壓編譯了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置內核各選項,如果沒有配置就無法下一步編譯,這里可以不要改任何東西)
#make
…
如果編譯沒有出錯。那麼恭喜你。你的開發環境已經搭建好了
三、了解驅動的基本知識
1. 設備號
1) 什麼是設備號呢?我們進系統根據現有的設備來講解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root 1, 3 2009-05-11 16:36 null
crw------- 1 root root 4, 0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty 5, 0 2009-05-11 16:36 tty
crw-rw---- 1 root tty 4, 0 2009-05-11 16:35 tty0
在日期前面的兩個數(如第一列就是1,3)就是表示的設備號,第一個是主設備號,第二個是從設備號
2) 設備號有什麼用呢?
l 傳統上, 主編號標識設備相連的驅動. 例如, /dev/null 和 /dev/zero 都由驅動 1 來管理, 而虛擬控制台和串口終端都由驅動 4 管理
l 次編號被內核用來決定引用哪個設備. 依據你的驅動是如何編寫的自己區別
3) 設備號結構類型以及申請方式
l 在內核中, dev_t 類型(在 中定義)用來持有設備編號, 對於 2.6.0 內核, dev_t 是 32 位的量, 12 位用作主編號, 20 位用作次編號.
l 能獲得一個 dev_t 的主或者次編號方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l 但是如果你有主次編號, 需要將其轉換為一個 dev_t, 使用: MKDEV(int major, int minor);
4) 怎麼在程序中分配和釋放設備號
在建立一個字元驅動時需要做的第一件事是獲取一個或多個設備編號來使用. 可以達到此功能的函數有兩個:
l 一個是你自己事先知道設備號的
register_chrdev_region, 在 中聲明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first 是你要分配的起始設備編號. first 的次編號部分常常是 0,count 是你請求的連續設備編號的總數. name 是應當連接到這個編號范圍的設備的名子; 它會出現在 /proc/devices 和 sysfs 中.
l 第二個是動態動態分配設備編號
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用這個函數, dev 是一個只輸出的參數, 它在函數成功完成時持有你的分配范圍的第一個數. fisetminor 應當是請求的第一個要用的次編號; 它常常是 0. count 和 name 參數如同給 request_chrdev_region 的一樣.
5) 設備編號的釋放使用
不管你是採用哪些方式分配的設備號。使用之後肯定是要釋放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2. 驅動程序的二個最重要數據結構
1) file_operation
倒如字元設備scull的一般定義如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也稱為設備驅動程序介面
定義在 , 是一個函數指針的集合. 每個打開文件(內部用一個 file 結構來代表)與它自身的函數集合相關連( 通過包含一個稱為 f_op 的成員, 它指向一個 file_operations 結構). 這些操作大部分負責實現系統調用, 因此, 命名為 open, read, 等等
2) File
定義位於include/fs.h
struct file結構與驅動相關的成員
l mode_t f_mode 標識文件的讀寫許可權
l loff_t f_pos 當前讀寫位置
l unsigned int_f_flag 文件標志,主要進行阻塞/非阻塞型操作時檢查
l struct file_operation * f_op 文件操作的結構指針
l void * private_data 驅動程序一般將它指向已經分配的數據
l struct dentry* f_dentry 文件對應的目錄項結構
3. 字元設備注冊
1) 內核在內部使用類型 struct cdev 的結構來代表字元設備. 在內核調用你的設備操作前, 必須編寫分配並注冊一個或幾個這些結構. 有 2 種方法來分配和初始化一個這些結構.
l 如果你想在運行時獲得一個獨立的 cdev 結構,可以這樣使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l 如果想將 cdev 結構嵌入一個你自己的設備特定的結構; 你應當初始化你已經分配的結構, 使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2) 一旦 cdev 結構建立, 最後的步驟是把它告訴內核, 調用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
說明:dev 是 cdev 結構, num 是這個設備響應的第一個設備號, count 是應當關聯到設備的設備號的數目. 常常 count 是 1, 但是有多個設備號對應於一個特定的設備的情形.
3) 為從系統去除一個字元設備, 調用:
void cdev_del(struct cdev *dev);
4. open 和 release
② 嵌入式工程師與後端開發哪個難
嵌入式工程師與後端開發相比還是嵌入式工程師比較難。嵌入式驅動工程師:編寫和移植各種晶元驅動(如音頻晶元),優化硬體設備驅動(如溫濕度感測器),得精通各種硬體介面協議(如I2C協議)、系統調度、信號量、鎖機制等等,開發難度最大。
該類開發者一般是軟硬體綜合型人才,一般的嵌入式驅動工程師指LINUX上的驅動開發工程師,需要精通Linux驅動框架(platform框架、input子系統框架等),結合晶元本身去編寫驅動,驅動的好壞很大程度上決定一個產品的好壞。
業界對驅動人才的定義是三年才算入門鉛孝,可見此門檻槐肆稿之高。
嵌入式工程師比後端開發難,因為嵌入雹李式需要學習和掌握的知識多,比如電子電路知識,模擬電路知識,電子英語,電子制圖,c需要,高等數學等
③ linux驅動程序結構框架及工作原理分別是什麼
一、Linux device driver 的概念x0dx0ax0dx0a系統調用是操作系統內核和應用程序之間的介面,設備驅動程序是操作系統內核和機器硬體之間的介面。設備驅動程序為應用程序屏蔽了硬體的細節,這樣在應用程序看來,硬體設備只是一個設備文件,應用程序可以象操作普通文件一樣對硬體設備進行操作。設備驅動程序是內核的一部分,它完成以下的功能:x0dx0ax0dx0a1、對設備初始化和釋放;x0dx0ax0dx0a2、把數據從內核傳送到硬體和從硬體讀取數據;x0dx0ax0dx0a3、讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據;x0dx0ax0dx0a4、檢測和處理設備出現的錯誤。x0dx0ax0dx0a在Linux操作系統下有三類主要的設備文件類型,一是字元設備,二是塊設備,三是網路設備。字元設備和塊設備的主要區別是:在對字元設備發出讀/寫請求時,實際的硬體I/O一般就緊接著發生了,塊設備則不然,它利用一塊系統內存作緩沖區,當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際的I/O操作。塊設備是主要針對磁碟等慢速設備設計的,以免耗費過多的CPU時間來等待。x0dx0ax0dx0a已經提到,用戶進程是通過設備文件來與實際的硬體打交道。每個設備文件都都有其文件屬性(c/b),表示是字元設備還是塊設備?另外每個文件都有兩個設備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個設備驅動程序的不同的硬體設備,比如有兩個軟盤,就可以用從設備號來區分他們。設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號一致,否則用戶進程將無法訪問到驅動程序。x0dx0ax0dx0a最後必須提到的是,在用戶進程調用驅動程序時,系統進入核心態,這時不再是搶先式調度。也就是說,系統必須在你的驅動程序的子函數返回後才能進行其他的工作。如果你的驅動程序陷入死循環,不幸的是你只有重新啟動機器了,然後就是漫長的fsck。x0dx0ax0dx0a二、實例剖析x0dx0ax0dx0a我們來寫一個最簡單的字元設備驅動程序。雖然它什麼也不做,但是通過它可以了解Linux的設備驅動程序的工作原理。把下面的C代碼輸入機器,你就會獲得一個真正的設備驅動程序。x0dx0ax0dx0a由於用戶進程是通過設備文件同硬體打交道,對設備文件的操作方式不外乎就是一些系統調用,如 open,read,write,close?, 注意,不是fopen, fread,但是如何把系統調用和驅動程序關聯起來呢?這需要了解一個非常關鍵的數據結構:x0dx0ax0dx0aSTruct file_operatiONs {x0dx0ax0dx0aint (*seek) (struct inode * ,struct file *, off_t ,int);x0dx0ax0dx0aint (*read) (struct inode * ,struct file *, char ,int);x0dx0ax0dx0aint (*write) (struct inode * ,struct file *, off_t ,int);x0dx0ax0dx0aint (*readdir) (struct inode * ,struct file *, struct dirent * ,int);x0dx0ax0dx0aint (*select) (struct inode * ,struct file *, int ,select_table *);x0dx0ax0dx0aint (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);x0dx0ax0dx0aint (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);x0dx0ax0dx0aint (*open) (struct inode * ,struct file *);x0dx0ax0dx0aint (*release) (struct inode * ,struct file *);x0dx0ax0dx0aint (*fsync) (struct inode * ,struct file *);x0dx0ax0dx0aint (*fasync) (struct inode * ,struct file *,int);x0dx0ax0dx0aint (*check_media_change) (struct inode * ,struct file *);x0dx0ax0dx0aint (*revalidate) (dev_t dev);x0dx0ax0dx0a}x0dx0ax0dx0a這個結構的每一個成員的名字都對應著一個系統調用。用戶進程利用系統調用在對設備文件進行諸如read/write操作時,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然後讀取這個數據結構相應的函數指針,接著把控制權交給該函數。這是linux的設備驅動程序工作的基本原理。既然是這樣,則編寫設備驅動程序的主要工作就是編寫子函數,並填充file_operations的各個域。x0dx0ax0dx0a下面就開始寫子程序。x0dx0ax0dx0a#include
④ 求教怎麼學習linux內核驅動
1.首先要了解為什麼要學習內核?下圖已表明,如果要從事驅動開發或系統研究,就要學習內核。
2.內核的知識就像下面的繩結一樣,一環扣一環,我們要解開它們,就必須要先找到線頭也就是內核中的函數介面。初學階段,我們一般不深入的研究內核代碼,會使用內核的介面函數就不錯了。
3.下面提供了如何學習這些內核函數的方法,就像解繩子一樣
4.學習內核的四步法則,思維導圖的設計尤為重要,這也是能否學習好內核的關鍵
5.語言基礎也需要扎實,所以需要把C語言鞏固鞏固
⑤ 學嵌入式linux需要先學什麼
剛入門的時來候,淘寶買一塊cortex m3開發板源即可入手,通過項目,你需要了解:任務調度、進程間通信、內存管理、設備驅動、文件系統、TCP/IP協議棧、同步非同步、中斷、軟體架構插件化等等基本原理,這些對你後面轉Linux應用開發,安卓開發,後台開發大有好處。
到這一步,就看自己職業方向想往哪裡發展,如果是想深入IOT物聯網做端雲連接,那麼可以把幾種基本匯流排驅動,I2C、SPI、USART理解透,如果是想擁抱互聯網轉入應用開發,那麼可以把基礎組件,如協議棧、文件系統吃透,BAT面試不是很難,問的都是這些基礎。
順便說一下,學東西就要學對市場有用的,不要過於學習屠龍之術,炫技給個人帶來不了財富,公司需要的是能幹活的人。
不準備講過於偏硬體的知識如Cortex-M3的多種中斷模式,操作寄存器組,晶元降噪等內容,而是專注於操作系統基本知識和項目經驗,這些對於開發者後面接觸Linux系統大有脾益,這些軟體開發經驗也是去互聯網公司看重的能力。如有需要學習Linux命令請如下查找:
⑥ android和Linux的區別
有以下三點區別:
1、Android沒有本地窗口系統,而Linux是有X窗口系統。
2、Android沒有glibc支持,而Linux是有glibc支持的。
3、Android是有自己專有的驅動程序。
雖然Android基於Linux內核,但是它與Linux之間還是有很大的差別。
(6)linux驅動框架擴展閱讀
Android專有的驅動程序
1、Android Binder 基於OpenBinder框架的一個驅動,用於提供 Android平台的進程間通信(InterProcess Communication,IPC)功能。源代碼位於drivers/staging/android/binder.c。
2、Android電源管理(PM) 一個基於標准Linux電源管理系統的輕量級Android電源管理驅動,針對嵌入式設備做了很多優化。源代碼位於:
kernel/power/earlysuspend.c
kernel/power/consoleearlysuspend.c
kernel/power/fbearlysuspend.c
kernel/power/wakelock.c
kernel/power/userwakelock.c
3、低內存管理器(Low Memory Killer) 比Linux的標銷雹逗準的OOM(Out Of Memory)機制更加靈活,它可以根據需要殺死進程以釋放需要的內存。源代碼位於 drivers/staging/ android/lowmemorykiller.c。
4、匿名共享內存(Ashmem) 為進程間提供大塊共享內存,同時為內核提供回收和管理這個內存的機制。源代碼位於mm/ashmem.c。
5、Android PMEM(Physical) PMEM用於向用戶空間提供連續的物理內存區域,DSP和某些設備只能工作在連續的物理內存上。源代碼位於drivers/misc/pmem.c。
6、Android Logger 一個輕量級的日誌設備,用於抓取Android系統的各種日誌。源代碼位於drivers/staging/android/logger.c。
7、Android Alarm 提供了一個定時器,用於把設備從睡眠狀態喚醒,同時它還提供了一個即使在設備睡眠時也會運行的時鍾基準肆態。源代碼位於drivers/rtc/alarm.c。
8、USB Gadget驅動 一個基於標准 Linux USB gadget驅動框架的設備驅動,Android的USB驅動是基於gaeget框架的。源代碼位於drivers/usb/gadget/。
9、Android Ram Console 為了提供調試功能,Android允許將調試日誌信息寫入一個被稱為RAM Console的設備里,它是一個基於RAM的Buffer。源代碼位於drivers/staging/android / ram_console.c。
10、Android timed device 提供了對虧賣設備進行定時控制的功能,目前支持vibrator和LED設備。源代碼位於drivers/staging/android /timed_output.c(timed_gpio.c)。
參考資料:網路——Android
網路——linux
⑦ 《Linux設備驅動開發詳解4.0》pdf下載在線閱讀全文,求百度網盤雲資源
《Linux設備驅動開發詳解4.0》網路網盤pdf最新全集下載:
鏈接: https://pan..com/s/1wxaYK87l11FDur15aS6FTQ
⑧ 解釋一下linux驅動程序結構框架及工作原理
一、Linux device driver 的概念
系統調用是操作系統內核和應用程序之間的介面,設備驅動程序是操作系統內核和機器硬體之間的介面。設備驅動程序為應用程序屏蔽了硬體的細節,這樣在應用程序看來,硬體設備只是一個設備文件,應用程序可以象操作普通文件一樣對硬體設備進行操作。設備驅動程序是內核的一部分,它完成以下的功能:
1、對設備初始化和釋放;
2、把數據從內核傳送到硬體和從硬體讀取數據;
3、讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據;
4、檢測和處理設備出現的錯誤。
在Linux操作系統下有三類主要的設備文件類型,一是字元設備,二是塊設備,三是網路設備。字元設備和塊設備的主要區別是:在對字元設備發出讀/寫請求時,實際的硬體I/O一般就緊接著發生了,塊設備則不然,它利用一塊系統內存作緩沖區,當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際的I/O操作。塊設備是主要針對磁碟等慢速設備設計的,以免耗費過多的CPU時間來等待。
已經提到,用戶進程是通過設備文件來與實際的硬體打交道。每個設備文件都都有其文件屬性(c/b),表示是字元設備還是塊設備?另外每個文件都有兩個設備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個設備驅動程序的不同的硬體設備,比如有兩個軟盤,就可以用從設備號來區分他們。設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號一致,否則用戶進程將無法訪問到驅動程序。
最後必須提到的是,在用戶進程調用驅動程序時,系統進入核心態,這時不再是搶先式調度。也就是說,系統必須在你的驅動程序的子函數返回後才能進行其他的工作。如果你的驅動程序陷入死循環,不幸的是你只有重新啟動機器了,然後就是漫長的fsck。
二、實例剖析
我們來寫一個最簡單的字元設備驅動程序。雖然它什麼也不做,但是通過它可以了解Linux的設備驅動程序的工作原理。把下面的C代碼輸入機器,你就會獲得一個真正的設備驅動程序。
由於用戶進程是通過設備文件同硬體打交道,對設備文件的操作方式不外乎就是一些系統調用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系統調用和驅動程序關聯起來呢?這需要了解一個非常關鍵的數據結構:
STruct file_operatiONs {
int (*seek) (struct inode * ,struct file *, off_t ,int);
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);
int (*select) (struct inode * ,struct file *, int ,select_table *);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file *,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}
這個結構的每一個成員的名字都對應著一個系統調用。用戶進程利用系統調用在對設備文件進行諸如read/write操作時,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然後讀取這個數據結構相應的函數指針,接著把控制權交給該函數。這是linux的設備驅動程序工作的基本原理。既然是這樣,則編寫設備驅動程序的主要工作就是編寫子函數,並填充file_operations的各個域。
下面就開始寫子程序。
#include <linux/types.h> 基本的類型定義
#include <linux/fs.h> 文件系統使用相關的頭文件
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
unsigned int test_major = 0;
static int read_test(struct inode *inode,struct file *file,char *buf,int count)
{
int left; 用戶空間和內核空間
if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )
return -EFAULT;
for(left = count ; left > 0 ; left--)
{
__put_user(1,buf,1);
buf++;
}
return count;
}
這個函數是為read調用准備的。當調用read時,read_test()被調用,它把用戶的緩沖區全部寫1。buf 是read調用的一個參數。它是用戶進程空間的一個地址。但是在read_test被調用時,系統進入核心態。所以不能使用buf這個地址,必須用__put_user(),這是kernel提供的一個函數,用於向用戶傳送數據。另外還有很多類似功能的函數。請參考,在向用戶空間拷貝數據之前,必須驗證buf是否可用。這就用到函數verify_area。為了驗證BUF是否可以用。
static int write_test(struct inode *inode,struct file *file,const char *buf,int count)
{
return count;
}
static int open_test(struct inode *inode,struct file *file )
{
MOD_INC_USE_COUNT; 模塊計數加以,表示當前內核有個設備載入內核當中去
return 0;
}
static void release_test(struct inode *inode,struct file *file )
{
MOD_DEC_USE_COUNT;
}
這幾個函數都是空操作。實際調用發生時什麼也不做,他們僅僅為下面的結構提供函數指針。
struct file_operations test_fops = {?
read_test,
write_test,
open_test,
release_test,
};
設備驅動程序的主體可以說是寫好了。現在要把驅動程序嵌入內核。驅動程序可以按照兩種方式編譯。一種是編譯進kernel,另一種是編譯成模塊(moles),如果編譯進內核的話,會增加內核的大小,還要改動內核的源文件,而且不能動態的卸載,不利於調試,所以推薦使用模塊方式。
int init_mole(void)
{
int result;
result = register_chrdev(0, "test", &test_fops); 對設備操作的整個介面
if (result < 0) {
printk(KERN_INFO "test: can't get major number\n");
return result;
}
if (test_major == 0) test_major = result; /* dynamic */
return 0;
}
在用insmod命令將編譯好的模塊調入內存時,init_mole 函數被調用。在這里,init_mole只做了一件事,就是向系統的字元設備表登記了一個字元設備。register_chrdev需要三個參數,參數一是希望獲得的設備號,如果是零的話,系統將選擇一個沒有被佔用的設備號返回。參數二是設備文件名,參數三用來登記驅動程序實際執行操作的函數的指針。
如果登記成功,返回設備的主設備號,不成功,返回一個負值。
void cleanup_mole(void)
{
unregister_chrdev(test_major,"test");
}
在用rmmod卸載模塊時,cleanup_mole函數被調用,它釋放字元設備test在系統字元設備表中佔有的表項。
一個極其簡單的字元設備可以說寫好了,文件名就叫test.c吧。
下面編譯 :
$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c –c表示輸出制定名,自動生成.o文件
得到文件test.o就是一個設備驅動程序。
如果設備驅動程序有多個文件,把每個文件按上面的命令行編譯,然後
ld ?-r ?file1.o ?file2.o ?-o ?molename。
驅動程序已經編譯好了,現在把它安裝到系統中去。
$ insmod ?–f ?test.o
如果安裝成功,在/proc/devices文件中就可以看到設備test,並可以看到它的主設備號。要卸載的話,運行 :
$ rmmod test
下一步要創建設備文件。
mknod /dev/test c major minor
c 是指字元設備,major是主設備號,就是在/proc/devices里看到的。
用shell命令
$ cat /proc/devices
就可以獲得主設備號,可以把上面的命令行加入你的shell script中去。
minor是從設備號,設置成0就可以了。
我們現在可以通過設備文件來訪問我們的驅動程序。寫一個小小的測試程序。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int testdev;
int i;
char buf[10];
testdev = open("/dev/test",O_RDWR);
if ( testdev == -1 )
{
printf("Cann't open file \n");
exit(0);
}
read(testdev,buf,10);
for (i = 0; i < 10;i++)
printf("%d\n",buf[i]);
close(testdev);
}
編譯運行,看看是不是列印出全1
以上只是一個簡單的演示。真正實用的驅動程序要復雜的多,要處理如中斷,DMA,I/O port等問題。這些才是真正的難點。上述給出了一個簡單的字元設備驅動編寫的框架和原理,更為復雜的編寫需要去認真研究LINUX內核的運行機制和具體的設備運行的機制等等。希望大家好好掌握LINUX設備驅動程序編寫的方法。
⑨ 驅動開發需要學什麼
驅動開發需要學的如下:
一、Android驅動的基礎知識
1、Android驅動是基於Linux驅動,強烈推薦閱讀Linux Device Driver3rd版,這本書講了Linux下設宴遊伍備驅動的基礎知識,要求反復細讀。
2、能讀懂和編寫一些C程序晌或。
3、能懂Java基礎,因為Framework層的代磨敬碼與驅動代碼聯系比較緊密,稍懂一些Java代碼,會發現對整個驅動框架的了解更加熟悉。
四、熱愛驅動開發和不斷學習
做Android驅動開發需要的是不斷的學習,時刻保持著一股激情,不斷的學習才能更好的完成日常的驅動開發任務,並能保持對開發的敏銳感覺。