首先理一理驅動/內核/應用程序的一些概念,以前總沒有具體的去關注過!
我們的pc直觀來看就是一堆電子元器件,怎么樣讓這堆元器件工作起來呢?當然就需要我們的驅動程序。
linux上的驅動程序實質上和我們當年的51單片機點亮led是一樣一樣的。pc上每個設備都是有自己的驅動的,包括鼠標/鍵盤和顯卡。
既然電腦上有這么多組件和每個組件的驅動,那工作的時候還不打架,你的擔心灰常正確,有個人解決了這個問題,然后他就成為了比爾蓋茨。
還有個人以一種無私的方式解決了這個問題,他就是林那廝.圖娃子。正是比爾先生的windows操作系統才讓使得讓大家像傻瓜一樣去用電腦,然而正是這種便捷,讓大家都忽視了每日都在使用的操作系統。操作系統使用灰常簡單,這都都因為大神級的程序員啊!所以今天便捷的互聯網社會源自千百萬個程序員夜以繼日的玩命啊!
好吧!我們回到正題,其實上面含沙射影也說了,我們可以形象描述為操作系統=所有驅動+系統的管理。這系統的管理包括不同模塊間的工作協調以及各種調度一樣,就像 一個馬路中間的交警。而我們一般認為所有驅動程序的總和就是系統的內核。
在linux系統下,系統內核分為三種類型,字符設備/塊設備/網絡設備。塊設備一般用於像U盤,光盤這些存儲設備,我們可以成塊成塊的去忘這些設備中投放數據,也可以訪問固定塊的數據,這就是我們形象的塊設備。至於字符設備,和塊設備剛好相反,就是它的輸入量一般是不確定的,比如串口。就是他什么時候有數據或者數據量都是不確定了,當然我們也不能隨意去訪問它的數據。
我一直覺得,計算機這玩意要想學的快,必須馬上做。當遇到問題時,要馬上看書,既要理論結合實際。有個很明顯的感覺,上學那會老師課堂講的總不知道要干啥?比如數電什么的?現在要來做東西,全都用上了,而且知道怎么回事了。
對了,還有一個應用程序,應用程序就不多說了,你在快播上看愛情電影時,便是一個很好的用應用程序的例子。
在pc系統中,我們的應用程序和系統程序(內核)是不在一個空間的,也就是說他們是存在鴻溝的。就是你應用程序和內核之間不是互聯互通的,中間需要一個保護的屏障,內核只向外提供接口,應用程序通過操作系統訪問內核接口。這樣防止小白們因無知而搞壞了系統。
這就在另一個方面說明了,驅動工程師壓力山大啊!驅動工程師可是直接編寫內核的人啊!應用軟件工程師程序寫壞了是一個程序的問題,驅動工程師一個模塊驅動寫壞了,系統可能就會受到影響,因此一個好的系統工程師必須是個細膩的男淫!
又羅嗦了這么多,趕緊我們的hello,word!這里我們采用模塊的方式,讓后動態加進內核!
補充一點,我們寫驅動的目的,最終都是要加進內核的。有兩種方式加進內核,一種是直接編譯進內核。
另一種就是這里的動態加入內核的。一般建議在驅動程序開發階段要采用動態加載。
關於驅動的寫法我們就直接看代碼吧!
//hello.c
//auther:heat nan
//programe:char driver-hello world
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL"); //內核2.6以上版本建議我們加上這個license
static int hello_init(void) //驅動入口
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
好了不多說了,這個代碼常見的就是兩份,一個是某開發板上帶的,一個是LDD那本書上第二章的。
我真不知道這樣復制來粘貼去真的好嘛?我真的為國人的創新而感到一絲絲擔憂!就不會把printk里面的字符給改了嗎?
好了,那我們就不多說了,入鄉隨俗吧!直接貼出某開發板的代碼!
某些人可能會糾結這個文件該建在哪里,我剛開始也有小疑問,后來就哪里順眼放哪里!可以單獨建立一個文件,放在里面。
接下來我們的驅動程序就寫完啦!沒錯真的寫完啦,下面咱們編譯。這里采用直接暴力的makefile的方法。
Makefile 文件:
obj-m:=heatnan.o
KERNELDIR:=/lib/modules/3.13.0-43-generic/build //現在才知道學英文干什么,kerneldir
PWD:=$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
下面來看看這個makefile文件,obj-m這句主要是說要編譯成模塊。
kerneldir這個說的很明白了,就是你內核頭文件所在,因為我們的模塊中使用了內核相關的函數,比如 輸出函數。所以我們要編譯這個驅動需要指定這個內核頭文件所在位置。一般在lib/modules目錄下,如果沒有的話需要下載內核的。
關於下面的解釋也都是一些程式的東西,這都是系統設計者為系統的可擴展所做出的一些工作。關於詳細的解釋。
詳見
http://www.embedu.org/Column/Column310.htm
好上面,工作做完后,輕點一下make。結果就出來了后綴諸如.ko.o的文件,這就證明成功了。
下面用insmod指令來動態的加載驅動程序,這個時候務必要切換到root權限。
加載之后發現木有反應,是不是有一點丹丹的憂桑。
不過不要擔心,問題還是可以解決的,printk是內核級別的函數,查看需要輸出:dmesg | tail
同時,也可以用lsmod列舉當下的正在進行的modules。
helloword到這里就結束了,雖然還沒碰到驅動開發的肉肉,但是還是遠遠看清楚了它的模樣!