第一次在android平台上单独编译内核模块并且insmod,过程比较难受,毕竟啥事第一次做都不怎么顺畅!
本文基于Android5.1 msm8909
因为笔者使用的平台物理串口只有两个,一个已经作为系统的debug调试串口,那就相当于只有一个串口供使用了,这样因为串口个数需求远大于一个,需要添加虚拟串口的驱动。
采取如下方法实现:
编写虚拟串口驱动
单独编译的时候,
1.创建驱动目录vcom
因为是单独编译,因此文件夹的位置可在任意处,笔者放在android源码的根目录下
2.准备.c .h Makefile 文件
.c 和 Makefile 文件是必须的
这里说下Makefile文件,因为笔者在这吃了个难受的亏
Makefile的编写语法,格式什么的,我这里就不多说了,不知道的朋友可以去查查相关资料
Makefile中有几个重要的点需要注意:第一个是编译采用的ARCH平台,如arm,arm64等;第二个是编译器的路径,这里需要知道绝对路径和相对路径的概念,为了稳保路径正确,我这里采用了绝对路径。第三个就是内核目录:这里我才用android源码编译过后的内核目录。Makefile内容如下所示,几个重要的点用箭头指明了:
ifneq ($(KERNELRELEASE),)
MODULE_NAME = hogovcom
$(MODULE_NAME)-objs := extport.o vcom.o
obj-m := $(MODULE_NAME).o
else
KERNELDIR ?= /home/adr/workspace/android_code/android5_1/code_7/LINUX/android/out/target/product/msm8909/obj/KERNEL_OBJ
PWD ?= $(shell pwd)
ARCH = arm
CROSS_COMPILE= /home/adr/workspace/android_code/android5_1/code_7/LINUX/android/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-4.8-
.PHONY: modules clean
modules:
$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.o *.mod.c .*.*.cmd *.ko *.order *.symvers
rm -rf .tmp_versions
endif
3.执行make指令
执行make的时候,可能会遇到一些错误,出错时可以阅读出错信息来进行纠错,笔者在make时遇到了如下错误,可供参考:
在编译完成并生成ko文件后,在android板上insmod发现出现了如下错误,这可以看到图中有两处类型的错误:
第一处Unknown symbol _GLOBAL_OFFSET_TABLE_ (err 0)
这个可能是你编译器不对的原因,笔者开始使用的并不是上图makefile中所示的编译器,而是同级目录下的带android字符的编译器,然后因为出错,我换成了不带android字符的编译器,结果重新make insmod,该错误解决
参考:ndk 编译android内核模块无法加载 解决方法_douniwan5788的博客-CSDN博客
第二处:咋的一看,这么多方法没找到,但不应该啊,make都过去了,为啥insmod的时候会有方法找不到,结果把多个文件整合成一个文件,在make insmod ,问题解决。 但~ 这也不是个办法啊,大家都知道,在C语言中,不能把所有的代码都放在一个.c文件里面,这样这个.c文件会很大,而且代码维护起来会很麻烦。那么开始思考,makefile多文件生成一个ko这个该咋做,百度到个链接得到一个思路(参考:linux C下多文件编译,以及Makefile的使用 - tangQ_Q - 博客园),然后,调换 vcom.o 和extport.o的位置,然后make insmod,问题解决,卧槽,还真是这个问题。对于这个问题,我理解的是因为我vcom.o 里面我是需要调用extport里面的函数的,如果我把extport放后面,这样ld链接的时候,先编译vcom链接,这个时候extport还没有编译链接,那么当然找不到相关函数,这里可能说的不清楚,有错误的地方请大家指点!