Linux下使用內核源碼單獨編譯某一模塊


 

 

1. 查看config配置項

進入需要編譯的目錄,我的目錄是 ./net/bridge,

 

sean@sean:/media/sean/b55f4db0-2560-4807-b8bf-b29a66db54e1/home/sean/work/tmp/kernel/linux-4.8/net/bridge$ ls
br.c         br_fdb.o      bridge.mod.c  br_if.o     br_ioctl.o      br_multicast.o        br_netfilter_ipv6.o  br_netfilter.o  br_nf_core.o      br_stp_bpdu.c  br_stp_if.o     br_sysfs_br.c  br_vlan.c   Makefile
br_device.c  br_forward.c  bridge.mod.o  br_input.c  br_mdb.c        br_netfilter_hooks.c  br_netfilter.ko      br_netlink.c    br.o              br_stp_bpdu.o  br_stp.o        br_sysfs_br.o  br_vlan.o   modules.order
br_device.o  br_forward.o  bridge.o      br_input.o  br_mdb.o        br_netfilter_hooks.o  br_netfilter.mod.c   br_netlink.o    br_private.h      br_stp.c       br_stp_timer.c  br_sysfs_if.c  built-in.o  Module.symvers
br_fdb.c     bridge.ko     br_if.c       br_ioctl.c  br_multicast.c  br_netfilter_ipv6.c   br_netfilter.mod.o   br_nf_core.c    br_private_stp.h  br_stp_if.c    br_stp_timer.o  br_sysfs_if.o  Kconfig     netfilter
sean@sean:/media/sean/b55f4db0-2560-4807-b8bf-b29a66db54e1/home/sean/work/tmp/kernel/linux-4.8/net/bridge$ 

查看Makefile,找到需要編譯的文件,並確認編譯的config參數,如下:
在這里插入圖片描述

2. 編譯

命令如下:

make CONFIG_BRIDGE_IGMP_SNOOPING=m -C  /home/sean/kernel/linux-4.8 M=/home/sean/kernel/linux-4.8/net/bridge  modules

或者

cd /home/sean/kernel/linux-4.8/net/bridge
make CONFIG_BRIDGE_IGMP_SNOOPING=m -C  /home/sean/kernel/linux-4.8 M=`pwd`  modules

然后手動將生成的*.ko拷貝到/lib/modules/2.6.19/kernel/對應的目錄即可。(由於我需要的文件只能編譯為.o,所以不需要拷貝)

運行depmod -a重新配置依賴關系,以后就可以通過modprobe fuse來加載fuse模塊了。

3. make 參數的說明:

$(MAKE) -C $(KDIR) M=$(PWD) modules

-C:后面的參數為linux內核的頂層目錄
M:后面的參數為需要編譯文件的目錄

4. 例子

1)模塊Makefile

ifneq ($(KERNELRELEASE),)
obj-m := mytest.o
mytest-objs := file1.o file2.o file3.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
endif

 

 

KERNELRELEASE 是在內核源碼的頂層Makefile中定義的一個變量,在第一次讀取執行此Makefile時,KERNELRELEASE沒有被定義,所以make將讀取執行else之后的內容。如果make的目標是clean,直接執行clean操作,然后結束。

當make的目標為modules或modules_install時,-C ( K E R N E L D I R ) 指 明 跳 轉 到 內 核 源 碼 目 錄 下 讀 取 那 里 的 M a k e f i l e ; M = (KERNELDIR)指明跳轉到內核源碼目錄下讀取那里的Makefile;M=(KERNELDIR)MakefileM=(PWD) 表明然后返回到當前目錄繼續讀入、執行當前的Makefile。

當從內核源碼目錄返回時,KERNELRELEASE已被被定義,kbuild也被啟動去解析kbuild語法的語句,make將繼續讀取else之前的內容。else之前的內容為kbuild語法的語句, 指明模塊源碼中各文件的依賴關系,以及要生成的目標模塊名。

2)Kconfig與內核Makefile

  • a. 使用Kconfig以及內核的Makefile可以在內核中添加自己的源代碼,並且可以添加內核配置選項,是否編進內核,是否以模塊的方式等;

  • b. 在內核某個目錄的Kconfig文件中可以配置各個選項的含義;在Makefile中指定如果配置了,該如何編譯;

如要在/driver/char中增加一個配置選項CONFIG_FISHING_POLE選項;

在driver/char/Kconfig文件中增加對該選項的說明:

config FISHING_POLE

      tristate “簡單說明” //tristate代表有三種方式,如為bool代表不能變為模塊

      default n         //默認是否選擇

      help

         ****         //一些幫助信息

 

 

在driver/char/Makefile中增加:

obj-$(CONFIG_FISHING_POLE)  += fishing.o

 

 

如果有多個源文件:

obj-$(CONFIG_FISHING_POLE)  += fishing.o

fishing-objs := fishing-main.o fishing-line.o

 

root@ubuntu:/opt/gopath/src/github.com/kata-containers/packaging/kernel/kata-linux-5.4.60-89/drivers/android# make   CONFIG_ANDROID_BINDER_IPC=m  -C  /opt/gopath/src/github.com/kata-containers/packaging/kernel/kata-linux-5.4.60-89   M=/opt/gopath/src/github.com/kata-containers/packaging/kernel/kata-linux-5.4.60-89/drivers/android
make: Entering directory '/opt/gopath/src/github.com/kata-containers/packaging/kernel/kata-linux-5.4.60-89'
  CC       kata-linux-5.4.60-89/drivers/android/binderfs.o
  CC      /kernel/kata-linux-5.4.60-89/drivers/android/binder_alloc_selftest.o
  AR       kernel/kata-linux-5.4.60-89/drivers/android/built-in.a
  CC [M]   kata-linux-5.4.60-89/drivers/android/binder.o
  CC [M]   packaging/kernel/kata-linux-5.4.60-89/drivers/android/binder_alloc.o
cat: / kernel/kata-linux-5.4.60-89/drivers/android/modules.order: No such file or directory
  Building modules, stage 2.
  MODPOST 0 modules
sed: can't read  packaging/kernel/kata-linux-5.4.60-89/drivers/android/modules.order: No such file or directory
cat: /opt/gopath/src/github.com/kata-containers/packaging/kernel/kata-linux-5.4.60-89/drivers/android/modules.order: No such file or directory
make: Leaving directory '/ /packaging/kernel/kata-linux-5.4.60-89'

 

 

不支持modulers

make modules

The present kernel configuration has modules disabled.
Type 'make config' and enable loadable module support.
Then build a kernel with module support enabled.

Makefile:1356: recipe for target 'modules' failed
make: *** [modules] Error 1

 

 

Linux-Kconfig總結與分析

CONFIG宏變量參數

  • bool:      表示該CONFIG宏只能選擇y(編譯內核)或者n(不編譯),不能選擇m(編譯為模塊)
  • tristate:  表示該CONFIG宏可以設置y/m/n三種模式(tristate)
  • string:    表示該CONFIG宏可以設為一串字符,比如#define CONFIG_XXX "config test"
  • hex:       表示該CONFIG宏可以設為一個十六進制,比如#define CONFIG_XXX 0x1234
  • int:         表示該CONFIG宏可以設為一個整數,比如#define CONFIG_XXX 1234
menuconfig MY_SYMBOL_TEST    #生成一個菜單宏項
bool "MY_SYMBOL_TEST"
default y

config MY_SYMBOL1
bool "my symbol is bool"
default y
depends on MY_SYMBOL_TEST
config MY_SYMBOL2
tristate "my symbo2 is tristate"
default m
depends on MY_SYMBOL_TEST    

config MY_SYMBOL3
string "my symbo3 is string"
default "test symbo3"
depends on MY_SYMBOL2 && MY_SYMBOL_TEST

config MY_SYMBOL4
hex "my symbo4 is hex"
range 0 0x2000                  #設置hex區間
default 0x1234
depends on MY_SYMBOL2 && MY_SYMBOL_TEST

config MY_SYMBOL5
int "my symbo5 is int" 
range 0 2000                     #設置int區間
default 1234
depends on MY_SYMBOL2 && MY_SYMBOL_TEST

效果如下所示:

 

新手上路:內核模塊入門

從最初學習使用Linux OS,到學習Linux內核,再到自己編寫內核模塊,順利實現模塊的裝載和卸載,這是一個非常有趣的過程。下面我將內核模塊的學習內容和大家分享,將學習Linux內核的快樂簡單的傳遞。

構造和運行模塊的過程

模塊源代碼 hds.c文件

# include <linux/module.h>  				//任何模塊都必須包含,定義了可動態加載到內核的模塊所需要的必要信息
# include <linux/init.h>    				//必須包含,包含了宏__init(指定初始化函數)和__exit(指定清除函數)
# include <linux/kernel.h>  				//里面包含常用的內核API,例如內核打印函數printk()
static int __init hds_init(void)    		//__init將函數hds_init()標記為初始化函數,在模塊被裝載到內核時調用hds_init()
{
    int sum = 0;
	int i;
    for(i = 1; i < 11; i++)		   			//函數功能為1-10累加求和
		sum +=i;
	printk(KERN_CRIT "Hello kernel\n");		//注意末尾不要忘記加換行\n,否則打印會出現某些小的錯誤
	printk(KERN_ALERT "sum is %d\n",sum);   
                      //打印級別設為<1>,將求和結果立即打印,可以在插入模塊后,在用戶態下用命令dmesg查看打印效果
	return 0;
}  
static void __exit hds_exit(void)			//清除函數,在模塊被卸載之前調用
{
	printk(KERN_ALERT "Goodbye kernel\n");  //在模塊卸載時,將Goodbye kernel這句話打印到日志
}	
module_init(hds_init);   					//引導內核 模塊從這里進來
module_exit(hds_exit);   					//引導內核 模塊從這里出去
MODULE_LICENSE("GPL");   					//(必選項) 模塊許可證,缺省此句,將導致內核被污染
MODULE_AUTHOR("hds");	 					//(可選項) 描述模塊作者
MODULE_DESCRIPTION("for fun");  			//(可選項) 描述模塊功能 

Makefile文件

obj-m:=hds.o						#根據make的自動推導原則,make會自動將源程序hds.c編譯成目標程序hds.o。
                                    #所有在配置文件中標記為-m的模塊將被編譯成可動態加載進內核的模塊。即后綴為.ko的文件。
CURRENT_PATH:=$(shell pwd)  		#參數化,將模塊源碼路徑保存在CURRENT_PATH中
LINUX_KERNEL:=$(shell uname -r) 	#參數化,將當前內核版本保存在LINUX_KERNEL中
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL) 	
                                    #參數化,將內核源代碼的絕對路徑保存在LINUX_KERNEL_PATH中
all:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules 	#編譯模塊
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean  	#清理

編譯模塊

$ make      

為方便在當前終端查看日志打印信息,在裝載模塊前輸入此命令

$ tail -f /var/log/kern.log &

裝載模塊

$ sudo insmod hds.ko

查看裝載的模塊

$ lsmod

卸載模塊

$ sudo rmmod hds

查看模塊是否已卸載

$ lsmod


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM