前言
提示:实战解决Debian 10.5 安装新内核后驱动编译环境设置问题
网上很多关于这方面的教程,内容陈旧,有的没有经过检验,照搬照抄,给初学者造成了一定的学习困难和理解误区。本人作为一个学习7年Linux 的爱好者,用相对新的系统,构建一个完整的实验环境,期待对初学者有一个很好的帮助。
提示:以下是本篇文章正文内容
一、实验环境
操作系统:Debain Linux 10.5,内核5.4.59(稳定版)。
二、实验步骤
1.手动编译新内核
Debian 10.5自带的4.19内核升级到5.4.59
需要的工具:
automake、build-essential [ 包含make、g++(包含gcc)等工具]、bison、flex、libelf-dev、libssl-dev、bc
安装命令:
sudo apt install -y automake build-essential bison flex libelf-dev libssl-dev bc
**注意:**源码最好放在/usr/src/目录下:
下载内核源码linux-5.4.59.tar.xz
解压命令
tar -xJvf linux-5.4.59.tar.xz
下载内核源码linux-5.4.59.tar.bz2
解压命令
tar -xjvf linux-5.4.59.tar.bz2
下载内核源码linux-5.4.59.tar.gz
解压命令
tar -xzvf linux-5.4.59.tar.gz
进入内核源码文件夹目录:
拷贝当前系统配置并为新内核生成配置(输入路径时用TAB键补全功能,加快输入,减少输错概率)
cp /boot/config-4.19.0-6-amd64 .config
生成配置文件:
make oldconfig ; make defconfig ; make menuconfig ; make xconfig ; make olddefconfig
常用:make menuconfig ; make olddefconfig ; make oldconfig ; make defconfig
具体区别:菜单化选择-繁锁,用系统配置-加变化更改,用现系统配置,用系统定义配置。不懂的网上搜索。
我的安装选择:
make olddefconfig
注释掉.config文件中四处配置(用搜索功能):
CONFIG_MODULE_SIG_ALL、CONFIG_MODULE_SIG_KEY、CONFIG_SYSTEM_TRUSTED_KEYS、CONFIG_DEBUG_INFO
查看cpu相关信息命令(补充知识)
①物理cpu数:主板上实际插入的cpu数量,可以数不重复的 physical id 有几个(physical id)
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
②cpu核数:单块CPU上面能处理数据的芯片组的数量,如双核、四核等 (cpu cores)
cat /proc/cpuinfo| grep "cpu cores"| uniq
③逻辑cpu数:简单来说,它可使处理器中的1颗内核,如2颗内核那样在操作系统中发挥作用。
cat /proc/cpuinfo| grep "processor"| wc -l
编译内核环节,我的设置(-j 设置线程数):
多次编译过用命令:
make mrproper
初次编译用命令:
make clean
编译:
make -j $(cat /proc/cpuinfo| grep "cpu cores"| uniq | cut -d: -f2)
合并命令:
make clean && make -j $(cat /proc/cpuinfo | grep "cpu cores"| uniq | cut -d: -f2)
耐心等待30分钟左右(视自己电脑速度),编译完成。
也可以:
make -j X modules
然后:
make -j X bzImage
安装内核模块:
sudo make modules_install
安装内核:
sudo make install
更新GRUB:
sudo update-grub
重启,检查新内核:
uname -r
删除旧内核:
查看有哪些旧内核:
dpkg -l | grep linux-image | awk '{print$2}'
此命令我得到两条结果:
linux-image-4.19.0-10-amd64
linux-image-amd64
删除内核命令:
sudo apt remove --purge linux-image-`uname -r`[替换成自己的版本号,这是现用版本号]
删除第一个就会顺带把第二个也删了。
2.配置内核驱动程序编译环境
系统自带内核编译环境构建:
sudo apt-get install linux-headers-`uname -r`[进入原始系统版本运行此命令]
命令执行结束后,安装在:
/usr/src/`uname -r`
新安装内核驱动程序编程环境构建:
己经编译过的内核目录 [ 确保此时系统使用新内核 ]:
运行命令:
make clean [删除编译文件,保留必要文件,减少文件体积]
我的编译过后用17G 这么大,删除后只有1G多,如果你的空间足够大的话可忽略。
进入目录:
cd /lib/modules/`uname -r`
查看有无build和source目录的链接,若无,执行命令:
ls -l
ln -s /lib/modules/`uname -r`/build /usr/src/`uname -r`
ln -s /lib/modules/`uname -r`/source /usr/src/`uname -r`
重要提示:
初次编译内核后,一定要记着用cp命令备份 Module.symvers 文件,位于内核根目录下。例如:
/usr/src/`uname -r`/Module.symvers
新解压未编译内核驱动编程环境构建:
运行命令
cp /boot/config-`uname -r` .config
make oldconfig && make prepare && make scripts "或者" make oldconfig && make prepare
若编译新内核时备份过 Module.symvers 文件,只需拷贝该文件到解压的内核源目录的根目录即可。例如:
cp 备份目录/Module.symvers /usr/src/`uname -r`/
如果未备份或者未编译过,只能运行 [ 漫长的等待 ]:
make -j$(cat /proc/cpuinfo | grep "cpu cores"| uniq | cut -d: -f2) modules
可以解决编译驱动程序时产生的“ Module.symvers is missing” 等问题。
提供一个可以运行的字符驱动源码:
Makefile文件:
obj-m := demo_chr_dev.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
@rm -f *.o *.ko *.mod.c *.symvers *.order *.mod.o
demo_chr_dev.c文件:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
static struct cdev chr_dev;
static dev_t ndev;
static int chr_open(struct inode *nd,struct file *filp)
{
int major=MAJOR(nd->i_rdev);
int minor=MINOR(nd->i_rdev);
printk("chr_open,major=%d,minor=%d\n",major,minor);
return 0;
}
static ssize_t chr_read(struct file *f,char __user *u,size_t sz,loff_t *off)
{
printk("In the chr_read() function!\n");
return 0;
}
struct file_operations chr_ops=
{
.owner=THIS_MODULE,
.open=chr_open,
.read=chr_read
};
static int __init demo_init(void)
{
int ret;
cdev_init(&chr_dev,&chr_ops);
ret=alloc_chrdev_region(&ndev,0,1,"chr_dev");
if(ret<0)
return ret;
printk("demo_init():major=%d,minor=%d\n",MAJOR(ndev),MINOR(ndev));
ret=cdev_add(&chr_dev,ndev,1);
if(ret<0)
return ret;
return 0;
}
static void __exit demo_exit(void)
{
printk("Removing chr_dev module...\n");
cdev_del(&chr_dev);
unregister_chrdev_region(ndev,1);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("DENNIS@AMDLINUXFGL");
MODULE_DESCRIPTION("A char device driver as an example.");
main.c测试文件:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define CHR_DEV_NAME "/dev/chr_dev"
int main()
{
int ret;
char buf[32];
int fd=open(CHR_DEV_NAME,O_RDONLY|O_NDELAY);
if(fd<0)
{
printf("open file %s failed!\n",CHR_DEV_NAME);
return -1;
}
read(fd,buf,32);
close(fd);
return 0;
}
总结
这里对文章进行总结:
本文使用Debain 10.5系统作为实验载体,就编译内核和构建驱动开发环境作了总结梳理,希望对小白有一定的帮助,也希望各位大神交流。