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

Linux設備驅動學習-模塊編程

1.linux設備驅動程序的作用
簡單的說,驅動程序告訴了我們可以提供了那些能力,但是沒有告訴我們怎麼使用這些能力。按照《linux設備驅動程序》上的說法,前一部分叫做”機制”,後面的叫作”策略”。linux設備驅動程序完成來自上層軟件的抽象調用,讓上層不用去關心底層到底怎麼實現。比如說音頻設備驅動,提供了一個接口 playsound().那麼上層只要去調用這個接口,就可以發音,而不必關心到底怎麼讓音頻設備發音。

2.內核模塊和用戶空間的應用程序的區別
內核模塊工作在內核態,應用程序工作在用戶態。這個概念是操作系統理論的基礎,不了解的,罰抄一編《操作系統》… 不同於應用程序是從頭到尾處理一個任務,內核模塊只是注冊下自己,以便服務將來的請求。模塊初始化的任務是為了將來調用模塊的函數作准備,就好像是說”我在這裡, 這是我能做的”。當模塊退出時,就好像是在說,”我不在這裡了,不要請我作任何事了”。
內核模塊和應用程序的區別還有,內核模塊在卸載的時候必須小心翼翼的將初始化時生成的資源給還原。雖然感覺很麻煩,但是無獨有偶,這也方便了我們測試程序,不用為了修改模塊後再調試而必須重啟。
在用戶空間寫程序時,可以調用並非自己寫的函數,比如printf,但是在內核中,因為沒有庫鏈接到內核中,所以絕大部分不能調用普通的頭文件,當然有例外。在內核中大部分的頭文件都定義在了include/linux和include/asm中。
還有一點是,如果用戶空間的程序出錯了,沒啥事,但是內核模塊出錯了,至少會終結當前的進程,極有可能導致系統崩潰。

3.hello world程序
理論暫且放一遍…看代碼.一個超級入門的程序,hello world.c。


這個模塊很簡單,只有四個部分。
我們先看最後兩行。module_init和module_exit是兩個宏,用來聲明模塊初始時調用的函數和卸載時調用的函數。參數就是對應的函數名。然後看初始化函數hello_init。函數聲明為static並不是必須的。一般來說,這個設備的函數並不需要被其他的內核模塊訪問,聲明為static就可以了。然後是__init,和__exit一樣是個標志,告訴內核這些函數或者結構體只是在初始化或者退出的時候用下,其他的時候不用。hello_init和hello_exit中只用到了一個printk函數,類似printf,不過在輸出時,需要先輸出消息的級別,比如KERN_ALERT。到此,一個非常簡單的hello world就完成了。下面編譯。

4.Makefile文件
在編譯之前講Makefile是必須的,因為如果沒有makefile的話每次編譯將會非常痛苦。至於Makefile,不講太多,給一個簡單的linux2.6下的模板吧.


內核模塊的makefile和一般C/c++程序的makefile有點不一樣,因為使用了kbuild。想了解makefile和kbuild的可以看linux的Documention。

5.編譯,加載內核模塊
將makefile寫好後,就可以在終端下切換到當前目錄,然後make就好了。當前前提是你有的include的文件和kernel sources tree.在/usr/src/linux-2.6*下有源代碼。在/usr/include/linux下有init.h和module.h。make成功後,目錄下應該生成了一個helloworld.ko,這是2.6的內核模塊的後綴。之後是加載到運行的內核中。sudo make install桌這手動輸入sudo insmod ./helloworld.ko也可以。還有一種加載內核模塊的命令是modprobe,這個比insmod更強大,可以自動搜索依賴。加載成功後,我們可以用lsmod來查看當前內核中的模塊,或者cat /proc/modules,都可以。而如果想看到helloworld模塊加載時輸出的信息,在Ubuntu 下可以去/var/log/kern.log文件中查看,或者使用dmesg命令。dmesg | tail -10. 如果想卸載模塊,可以用rmmod命令。sudo rmmod helloworld。

Copyright © Linux教程網 All Rights Reserved