【Linux驅動編程】多個源文件(platform driver)編譯成一個模塊

platform 驅動

  linux驅動最開始採用的是純驅動的寫法,驅動工程師只需實現一個功能驅動(driver),所有功能都集中在這個驅動。接着linux內核將設備(device)和驅動(driver)分離,引入了platform總線驅動框架,內核實現platform總線,驅動工程師實現platform deviceplatform driver,方便內核管理驅動和提升驅動開發效率。到後來,linux內核將板級信息剝離,不再將板級信息編譯到內核,而引入設備樹(dtb)概念,以設備樹文件描述板級信息,驅動通過獲取設備樹描述信息執行相關過程。此時,驅動工程師編寫驅動時則需要實現設備樹dtsplatform driver,即是用設備樹代替platform device

在這裏插入圖片描述

linux驅動衍變圖

  目前,現在linux主流驅動開發都是採用第三種方式,linux內核較低版本或者歷史維護性項目會採用第二種,甚至仍採用第一種的傳統方式。對於第二種驅動開發方式,我們一般建立兩個源碼文件,分別是dev_xxx.cdrv_xxx.cdev_xxx.c用於描述匹配驅動的信息,包括驅動名稱(name)、id、內存映射(memory),然後註冊當前platform device信息,提供給platform driver匹配(probe);drv_xxx.c則爲實際驅動的功能實現,設備驅動的初始化、資源分配(主次設備號、內存空間)、註冊、註銷以及提供linux標準虛擬文件系統接口(open/read/write/ioctl/mmap)。


實現

  不僅僅是platform驅動,對於包含多個源碼文件(.c)的,編譯成一個驅動模塊文件(.ko)的思路和方法都是類似的,都可以使用該方式。

【1】 各個源碼文件的初始化函數和析構函數聲明爲全局,最終在一個文件調用,並由module_initmodule_exit註冊到內核
【2】Makefile將所有目標文件鏈接爲一個文件


  在“Linux 字符驅動之platform框架”文章中的platform字符設備驅動,把dev_mem.cdrv_mem.c分別編譯成dev_mem.kodrv_mem.ko模塊文件,使用時也需將兩個模塊文件分別insmod到內核。現修改源碼和Makefile將其編譯爲一個模塊文件。

在這裏插入圖片描述

當前源碼目錄樹

【1】屏蔽dev_mem.c模塊初始化和析構函數

module_init(memory_dev_init);
module_exit(memory_dev_exit);
MODULE_LICENSE("GPL");

一個模塊只能擁有一個初始化和析構接口,即是一對module_init和module_exit,如果存在多個、接口,會導致編譯失敗。


【2】增加dev_mem.h頭文件,將構造初始化和析構函數聲明爲全局

extern int __init memory_dev_init(void);
extern void __exit memory_dev_exit(void);

【3】 在drv_mem.c模塊初始化和析構函數分別增加上dev_mem.h聲明的函數

static int __init memory_drv_init(void)
{
	memory_dev_init();
	return platform_driver_register(&memory_drv);
}

static void __exit memory_drv_exit(void)
{
	memory_dev_exit();
    platform_driver_unregister(&memory_drv);
}

【4】 修改Makefile,把所有編譯的目標文件鏈接成一個可執行文件

ifeq ($(KERNELRELEASE),)

KERNELDIR = /usr/src/linux-headers-4.15.0-91-generic
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf *.o *.ko .mod.o *.mod.c *.symvers *.order

else
	obj-m := devmem.o
	devmem-objs = dev_mem.o drv_mem.o
endif

  • obj-m := devmem.o,將代碼編譯爲devmem.ko模塊,-m表示編譯成模塊,-y表示編譯到內核

  • devmem-objs = dev_mem.o drv_mem.o,將所有目標文件(dev_mem.o、drv_mem.o)鏈接爲一個執行文件

  假設有更多個源碼文件,Makefile文件也是類似的

obj-m := object_name.o
devmem-objs = source0.o source1.o source2.o source3.o

在這裏插入圖片描述

修改後源碼目錄樹

【5】執行make -j4編譯,在當前文件生成指定文件名的驅動模塊

在這裏插入圖片描述

  接下來的加載驅動步驟是相同的,執行sudo insmod devmem.ko即可把dev_memdrv_mem加載到內核。


代碼倉庫

【1】https://github.com/Prry/linux-drivers/tree/master/devmem_platform

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章