Ubuntu驱动和内核源码树编译踩坑记录

 本次驱动编译主要是通过编译源码树来进行编译,过有关问题主要是编译源码树产生。通过linux-headers编译驱动是更为简单方便的,也是更为推荐的方法——本人后来试过此方法,一次成功,故没有相关踩坑记录:)。

ps:红色链接须重点查看

1.Ubuntu内核源码

        ubuntu内核源码开源,且与linus维护的linux kernel存在微小区别

        linus维护的linux kernel:

        https://github.com/torvalds/linux

        ubuntu内核源码git仓库:

        kernel.ubuntu.com

        https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/focal

        focal为ubuntu20.04名字,查看其他版本源码需将focal换为其他系统的名字

       launchpad.net 是维护Ubuntu GNU/Linux 发行版所使用的一个集代码管理,Bug 追踪,翻译等多种功能为一体的在线平台,由Canonical 公司开发和维护,Canonical 公司就是ubuntu的公司。

        查看ubuntu系统名可通过以下链接:

        Ubuntu in Launchpad

        https://zh.wikipedia.org/wiki/Ubuntu

        或者通过命令查询

u@u-pc:~$ lsb_release -a 
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal

          codename为ubuntu代号

ubuntu内核源码树官方下载教程如下:Kernel/SourceCode - Ubuntu Wiki

其他下载方法: 

Ubuntu 下获取和编译内核源码的方法 :: Shaocheng.Li — Hello Friends

ubuntu发行版内核源码下载 - 沐多 - 博客园 (cnblogs.com)

2.ubuntu内核版本相关问题

        查看完整内核版本命令

cat /proc/version_signature

        内核版本含义:

        Ubuntu kernels from Canonical | Ubuntu

        

ABI可简单理解为API,具体介绍:KernelTeam/BuildSystem/ABI - Ubuntu Wiki

 linux-source包不使用上述命令规范,例如linux-source-5.4.0就是5.4.0-150.167,可见

Ubuntu – 在 focal 中的 linux-source-5.4.0 软件包详细信息

3.通过源码树编译驱动

 0.完整教程: 

 Building External Modules — The Linux Kernel documentation

 Linux驱动实践:带你一步一步编译内核驱动程序 - IOT物联网小镇 - 博客园 (cnblogs.com)

【Linux】驱动模块的 编译与加载_linux驱动模块编译_Xav Zewen的博客-CSDN博客

Ubuntu 14.04.2安装内核源码树以及编译_51CTO博客_ubuntu 编译内核

如何编译linux驱动ko_linux驱动编译ko_liyinuo2017的博客-CSDN博客

1.通过defconfig生成.config

Linux内核指令make defconfig做了什么事情_HMJ_的博客-CSDN博客

修改Linux Kernel defconfig的标准方法 - 君の内存 (adtxl.com)

linux kernel 编译的过程中 make defconfig、 make menuconfig、 make savedefconfig、 make olddefconfig 的含义_51CTO博客_linux使用make编译 如果对linux kernel了解较深,可跳过此步

以目标机为x64架构为例:

#O=build表示编译文件输出目录为build,防止编译生成文件污染源码目录,输出目录可自定义
#一旦选择了输出目录,后续均在此目录操作
#若一次执行了make O=build1 x86_64_defconfig,make O=build2 x86_64_defconfig,则会产生
#build1,build2两个目录,两份输出
#x86_64_defconfig 在arch/x86/configs/x86_64_defconfig
make O=build x86_64_defconfig

2.通过menuconfig选择要编译的模块

【整理】make config,make menuconfig,make oldconfig,make xconfig,make defconfig,make gconfig – 在路上 (crifan.com)

[config]关于make *config - aaronGao - 博客园 (cnblogs.com)

几个make config的作用_bytxl的博客-CSDN博客

Linux 内核配置机制(make menuconfig、Kconfig、makefile)讲解_dianhuiren的博客-CSDN博客

make O=build menuconfig

*表示编译到内核中,M表示以模块形式编译

3.生成编译所需信息

#理论上二者均可,但在ubuntu14中,仅make O=build prepare有效
make O=build prepare
make O=build moudles_prepare

To build external modules, you must have a prebuilt kernel available that contains the configuration and header files used in the build. Also, the kernel must have been built with modules enabled. If you are using a distribution kernel, there will be a package for the kernel you are running provided by your distribution.

An alternative is to use the "make" target "modules_prepare." This will make sure the kernel contains the information required. The target exists solely as a simple way to prepare a kernel source tree for building external modules.

NOTE: "modules_prepare" will not build Module.symvers even if CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be executed to make module versioning work.

linux/Documentation/kbuild/modules.rst at 5bfc75d92efd494db37f5c4c173d3639d4772966 · torvalds/linux (github.com)

4.编译

#根据.config编译整个内核
#j4表示以4进程编译
make O=build -j4
#仅编译hid-cp2112驱动,但仍需上述几步,所使用的的头文件也是该驱动所在linux源码树提供,而非系统提供
make O=build drivers/hid/hid-cp2112.ko

5.清理

编译过程中可能会出现各种问题,当修复好问题后,需清理输出目录再次编译

make O=build clean      #删除大多数的编译生成文件, 但是会保留内核的配置文件.config, 还有足够的编译支持来建立扩展模块
make O=build mrproper   #删除所有的编译生成文件, 还有内核配置文件, 再加上各种备份文件
make O=build distclean  #mrproper删除的文件, 加上编辑备份文件和一些补丁文件。

6.安装驱动

方法一:

进入hid-cp2112.ko驱动模块文件所在的目录,然后直接insmod  hid-cp2112.ko 

insmod hid-cp2112.ko

方法二

将hid-cp2112.ko文件拷贝到原hid-cp2112.ko所在路径(/lib/modules/5.4.0-139-generic/kernel/drivers/hid/)。然后 depmod(会在/lib/modules/5.4.0-139-generic/kernel/drivers/hid/目录下生成modules.dep和modules.dep.bb文件,表明模块的依赖关系) 最后 modprobe hid-cp2112(注意这里无需输入.ko后缀) 即可。

#以下操作均需root权限
#以hid-cp2112.ko为例,因ubuntu自带hid-cp2112驱动,所以须先做备份
cp /lib/modules/5.4.0-139-generic/kernel/drivers/hid/hid-cp2112.ko /lib/modules/5.4.0-139-generic/kernel/drivers/hid/hid-cp2112.ko.bak
#此时位于自己编译的hid-cp2112.ko同一目录,将自己编译的hid-cp2112驱动复制到目的路径
cp hid-cp2112.ko /lib/modules/5.4.0-139-generic/kernel/drivers/hid/hid-cp2112.ko
depmod
modprobe hid-cp2112

注:两种方法的区别

modprobe和insmod类似,都是用来动态加载驱动模块的,区别在于modprobe可以解决load module时的依赖关系,它是通过/lib/modules/$(uname-r)/modules.dep(.bb)文件来查找依赖关系的;而insmod不能解决依赖问题。也就是说,如果你确定你要加载的驱动模块不依赖其他驱动模块的话,既可以insmod也可以modprobe,当然insmod可以在任何目录下执行,更方便一些。而如果你要加载的驱动模块还依赖其他ko驱动模块的话,就只能将模块拷贝到上

述的特定目录,depmod后再modprobe。

#查看已加载驱动
lsmod
#卸载驱动hid-cp2112.ko
rmmod hid-cp2112.ko
#查看已加载的hid-cp2112驱动信息
modinfo hid-cp2112
#查看当前目录下的hid-cp2112.ko的驱动信息
modinfo hid-cp2112.ko

相关问题

1.gcc版本切换问题

#用于选择gcc版本
sudo update-alternatives --config gcc

相关参考:

ubuntu 14.04 升级到 gcc 5 // Neurohazard (blkstone.github.io)

Ubuntu 1804 gcc、g++不同版本的切换 - 简书 (jianshu.com)

2.内核模块的vermagic相关问题

vermagic遇到问题务必看完这两个帖子,能解决大部分问题:

内核模块的version magic 你知多少?-OpenEdv-开源电子网

[转载]linux内核模块版本检查 - 君の内存 (adtxl.com)

其余相关:

向linux内核版本号添加字符/为何有时会自动添加“+”号_xiaofeng_yan的博客-CSDN博客

git - Don't add "+" to linux kernel version - Stack Overflow

Linux kernel 在 Git 目录和 SVN 目录编译行为不一致的解决方法 - 后台 / 嵌入式全栈之路 - SegmentFault 思否

内核模块编译怎样绕过insmod时的版本检查 - kk Blog —— 通用基础 (abcdxyzk.github.io)

Linux内核模块签名与版本检查机制 | clingfei

解析 Linux 内核可装载模块的版本检查机制【转】 - Sky&Zhang - 博客园 (cnblogs.com)

取消编译出的模块信息带有加号的方法

例如:

u@u-pc:~/code/linux/build/drivers/hid$ modinfo hid-cp2112.ko
filename:       /home/y/code/linux/build/drivers/hid/hid-cp2112.ko
license:        GPL
author:         David Barksdale <dbarksdale@uplogix.com>
description:    Silicon Labs HID USB to SMBus master bridge
alias:          hid:b0003g*v000010C4p0000EA90
depends:        
intree:         Y
vermagic:       4.4.0+ SMP mod_unload modversions 
parm:           gpio_push_pull:GPIO push-pull configuration bitmask (int)

4.4.0后面带有加号的原因是下载源码通过git下载,目录中带有git信息,并对源码进行了修改,导致编译出的模块带有+号,可在编译时使用参数LOCALVERSION取消掉+号

make LOCALVERSION= O=build drivers/hid/hid-cp2112.ko

原因如下:在scripts/setlocalversion中有注释:

append a plus sign if the repository is not in a clean annotated or signed tagged state (as git describe only looks at signed or annotated tags - git tag -a/-s) and LOCALVERSION= is not specified

翻译过来就是:

如果git仓库不是在一个干净的annotated or signed tagged的状态,且LOCALVERSION= 没有被指明,则添加一个加号

# localversion* files in the build and source directory
res="$(collect_files localversion*)"
if test ! "$srctree" -ef .; then
	res="$res$(collect_files "$srctree"/localversion*)"
fi

# CONFIG_LOCALVERSION and LOCALVERSION (if set)
res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"

# scm version string if not at a tagged commit
if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
	# full scm version string
	res="$res$(scm_version)"
else
	# append a plus sign if the repository is not in a clean
	# annotated or signed tagged state (as git describe only
	# looks at signed or annotated tags - git tag -a/-s) and
	# LOCALVERSION= is not specified
	if test "${LOCALVERSION+set}" != "set"; then
		scm=$(scm_version --short)
		res="$res${scm:++}"
	fi
fi

echo "$res"

annotate tag和sign tag含义可参考:

Git supports two types of tags: lightweight and annotated.

A lightweight tag is very much like a branch that doesn’t change — it’s just a pointer to a specific commit.

Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). It’s generally recommended that you create annotated tags so you can have all this information; but if you want a temporary tag or for some reason don’t want to keep the other information, lightweight tags are available too.

If you have a GPG private key set up, you can now use it to sign new tags. All you have to do is use -s instead of -a:

Git - Signing Your Work (git-scm.com)

Git - Tagging (git-scm.com)

其余参考资料:

ubuntu - Where to get linux "5.4.0-77-generic" kernel source? - Unix & Linux Stack Exchange

Kernel/SourceCode - Ubuntu Wiki

How can I prepare a Linux source tree so an external module can be compiled against it? - Stack Overflow

内核编译时, 到底用make clean, make mrproper还是make distclean_make清除编译_AyaoGGLi的博客-CSDN博客

Linux下加载.ko驱动模块的两种方法:insmod与modprobe_insmod : short read_coollh的博客-CSDN博客

Building External Modules — The Linux Kernel documentation

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值