樹莓派的內核模塊編程之Hello World

引言

樹莓派所使用的操作系統是基於linux內核開發的,由於linux內核完全免費公開,因此我們可以修改樹莓派的操作系統,實現對樹莓派更深層次的掌控。本文主要介紹樹莓派內核模塊編程的基礎知識,為以後的深入學習奠定基礎。

一、什麼是內核模塊?

內核模塊是可以在linux操作系統運行過程中,裝載或卸載於linux內核的代碼段。內核模塊可以在不需要重啟操作系統的情況下擴展linux內核的功能。最為典型的內核模塊就是設備驅動器,這種內核模塊主要實現的功能是控制與計算機系統相連接的硬件。

二、內核模塊與應用程序區別

大多數小型或中型規模的應用程序均是按照代碼指示一次性完成某個任務。而內核模塊則需要先在內核中完成註冊與初始化,目的是服務於未來的任務請求,當系統用戶認為不需要該模塊時,可以將其從內核中卸載。換句話說,每個內核模塊都有一個初始化函數與卸載函數,初始化函數的功能是告訴linux內核“我在這裡,我可以完成這些功能,用戶有這方面請求可以讓我來完成”。這種編程方式有點類似於事件驅動的編程方法。值得注意的是,並不是所有的應用程序是事件驅動的,但所有的內核模塊均是事件驅動的。卸載函數的功能則是將內核模塊從linux內核中卸載,這一點也是內核模塊與應用程序的主要區別。應用程序完成相關功能後會自動關閉或退出,而內核模塊則需要通過rmmod命令啟動卸載函數從而關閉或退出。

三、Hello World內核模塊

學習過編程的讀者都知道,大多數編程教材都是以“Hello World”程序示例為開端,來說明程序代碼的基本特徵。雖然本文主要講解的是內核模塊,但仍會遵從編程教材慣例,以“Hello World”內核模塊為示例說明內核模塊的基本特徵。

Hello World內核模塊代碼,即hello.c文件,如下圖所示:

樹莓派的內核模塊編程之Hello World

上述代碼前三行是添加內核模塊所需的三個宏文件。隨後hello_init函數與hello_exit函數是內核模塊初始化與卸載函數。在2.3.13版本的linux內核以前,內核模塊的初始化函數與卸載函數必須分別使用init_module與cleanup_module作為函數名。從2.3.13版本的linux內核以後,可以自定義初始化函數與卸載函數的函數名,但同時必須使用module_init與module_exit指定初始化函數與卸載函數,如上圖16與17行所示。

細心的讀者會發現上述代碼使用了printk函數來輸出字符串,而不是printf。這是由於基於linux內核的操作系統分為內核空間與用戶空間,printf是由標準C庫函數所定義的輸出函數,而標準C庫函數運行於用戶空間,同時又由於內核空間與用戶空間不能直接通信,因此運行於內核空間的內核模塊不能使用標準C庫函數,也就不能使用printf函數,所以linux內核需要自己的輸出函數printk。printk函數中的KERN_ALERT是優先級信息,printk函數的優先級一共有個8種,分別是KERN_EMERG、KERN_ALERT、KERN_CRIT、KERN_ERR、KERN_WARNING、KERN_NOTICE、KERN_INFO與KERN_DEBUG。KERN_EMERG優先級最高,該優先級下的信息會直接顯示在終端中,其他優先級信息需要通過dmesg命令查看。如果printk函數中沒有指定優先級,則會默認使用kernel/printk.c文件中DEFAULT_MESSAGE_LOGLEVEL定義的優先級。

上述代碼最後三行說明了該模塊的相關信息,分別是模塊許可證信息、作者信息與模塊描述信息,這些信息並不是強制要求的,但如果缺少MODULE_LICENSE信息則會在編譯模塊的過程中給出警告,有時也會報錯。linux內核認可的模塊許可證包括“GPL”、“GPL and additional rights”、“Dual BSD/GPL”與“Proprietary”。

除了hello.c文件外,內核模塊的編譯還需要Makefile文件,該文件代碼如下圖:

樹莓派的內核模塊編程之Hello World

上述代碼中,obj-m表示把文件hello.o作為內核模塊進行編譯,不要編譯到內核中,同時還會生成一個"hello.ko"文件。make -c指明瞭內核源碼的所在目錄,樹莓派官方系統通常不包含內核源碼,因此需要使用sudo apt-get install raspberrypi-kernel-headers命令來下載,該命令會在/usr/src/目錄下保存樹莓派系統的內核源碼。安裝與卸載內核模塊分別使用insmod與rmmod命令,為了操作方便,我們將這兩個命令寫在Makefile文件中。

將hello.c與Makefile兩個文件保存在同一個文件夾下,在終端分別輸入sudo make、sudo make install與sudo make uninstall命令來編譯、安裝與卸載內核模塊,命令效果如下圖:

樹莓派的內核模塊編程之Hello World

隨後我們還可以輸入dmesg | grep “world”命令查看內核模塊輸出的信息,效果如下圖:

樹莓派的內核模塊編程之Hello World

至此,內核模塊的基本特徵已說明完畢,如有建議與疑問歡迎交流。


分享到:


相關文章: