【树莓派Linux内核开发】入门实操篇(虚拟机Ubuntu环境搭建+内核源码获取与配置+内核交叉编译+内核镜像挂载)
文章目录
- 【树莓派Linux内核开发】入门实操篇(虚拟机Ubuntu环境搭建+内核源码获取与配置+内核交叉编译+内核镜像挂载)
- 一、搭建Ubuntu环境
- 二、树莓派等芯片带操作系统的启动过程
- 1.x86、Intel、windows等设备的启动过程
- 2.嵌入式产品(树莓派、mini2440、mini6410、nanopi、海思、RK(瑞芯微) )的启动过程
- 3.安卓操作系统的启动过程
- 4.小扩展
- 三、树莓派Linux内核源码简单认知
- 1.linux内核认知
- 2.Linux文件系统分区
- 四、树莓派Linux内核源码配置
- 1.内核源码配置原因
- 2.内核源码配置方法
- 2.1 cp 厂家.config
- 2.2 make menuconfig 通过菜单一项项配置(通常是基于厂家的config来配置)
- 2.3 完全自己来(略)
- 五、树莓派 linux 内核源码编译并运行
一、搭建Ubuntu环境
ubuntu1804_5">1.ubuntu18.04镜像下载
打开ubuntu18.04镜像传送门,进入到主页
往下滑,找到相应镜像并下载
等待镜像下载完毕即可
2.VMware软件安装
- VMware是一款运行在windows系统上的虚拟机软件,可以虚拟出一台计算机硬件,方便安装各类操作系统
进入VMware官网传送门,来到主页,往下滑,选着适合的版本进行下载
下载完成后,双击打开安装应用
点击下一步
勾选我接受
,继续下一步
选择自己的安装路径
,继续下一步
全部取消勾选
,继续下一步
最后,点击下一步
,开始安装
安装完成
咳咳,最后这部分就交给大家了
MC60H-DWHD5-H80U9-6V85M-8280D
3.安装镜像,创建虚拟机
打开VMware,点击创建新的虚拟机
我这里是选择自定义(看自己需求),然后进入下一步
直接下一步
选择好之前下载好的镜像文件,接着下一步
填写好安装信息,继续下一步(用户名有格式要求,不符合的会有提示)
取好虚拟机名字,选择一个磁盘空间比较大的位置,继续下一步
根据自己电脑配置量力而行(一般都这么操作也问题不大),继续下一步
这里就采用推荐内存了,2G
看情况,我这里选择桥接模式
后边都选推荐
创建虚拟磁盘
默认20G,下一步即可
开始创建
等待创建完毕即可
创建完毕,登录成功
4.虚拟机安装基础软件(安装过程有询问,直接回车或者Y)
4.1 安装vim
输入命令vi hello.c
,发现方向键不好用,系统软件比较古老
arsen@ubuntu:~$ vi hello.c
输入命令 sudo apt-get install vim
进行下载安装
arsen@ubuntu:~$ sudo apt-get install vim
安装完后再次vi hello.c
,发现颜色变了,操作也好使起来了
若发现上不了网,则进行如下操作
打开虚拟机设置,选择桥接模式
检查编辑里的 虚拟网络编辑器
检查里面的桥接模式(这里的ubuntu18的虚拟机已经帮桥接好,没有桥接模式的显示)
4.2 安装gcc(不会就面向百度开发)
编写完测试代码hello.c,发现没有gcc工具进行编译
面向百度后,得到下面命令,该命令将安装一堆新包,包括gcc,g++和make工具
sudo apt install build-essential
安装好后,进行编译,运行成功(应该加个\n的)
4.3 安装ifconfig
输入命令ifconfig
,发现运行失败
面向百度后,输入安装命令
sudo apt install net-tools
一开始遇到了安装失败的问题,后面把报错信息面向百度/CSDN后,得到参考解决方法,先弄两条命令再安装
报错信息:
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
解决方法:
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/dpkg/lock
sudo apt install net-tools
安装成功
5.添加共享文件夹(虚拟机上默认路径是 /mnt/hgfs/share)
点开虚拟机的设置
在选项里,启动并添加
选择本地电脑的文件夹路径,设置好此文件夹在虚拟机中的名字,继续下一步
完成添加,并确定
添加好后,虚拟机上的共享文件夹默认路径是 /mnt/hgfs/share
6.拷贝树莓派Linux内核源码和交叉编译工具链
6.1 下载内核源码和工具链
先到树莓派Linux内核源码地址,选择适合自己树莓派版本的,把源码下载到本地,放到共享文件夹下
版本查询
树莓派上运行 uname -r(演示一下)
uname -r
(我的树莓派是3B+,烧录的镜像是官方的标准镜像,看上面的内核版本我应该下载6.xx的才对,这里下错了,不过问题不大,只是测验,但对应版本的才能进行驱动和运行编译出来的东西)
传送门
6.2 解压并配置环境变量
继续操作上面的虚拟机,删除当前目录下的所有文件(没啥用的文件)
rm * -rf
接着,使用命令创建一个SYSTEM文件夹并进入
mkdir SYSTEM
cd SYSTEM
然后,使用 cp 命令,把我们在电脑上下载好的文件拷贝到虚拟机的当前目录
cp /mnt/hgfs/share/linux-rpi-4.19.y.zip .
cp /mnt/hgfs/share/tools-master.zip .
使用uzip命令解压压缩包
(这里显示我没有uzip,而且安装uzip还失败了,报错:E: Unable to locate package uzip)
arsen@ubuntu:~/SYSTEM$ ls
linux-rpi-4.19.y.zip tools-master.zip
arsen@ubuntu:~/SYSTEM$ uzip tools-master.zip Command 'uzip' not found, but there are 16 similar ones.arsen@ubuntu:~/SYSTEM$ sudo apt-get install uzip
[sudo] password for arsen:
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package uzip
arsen@ubuntu:~/SYSTEM$
最后,问题解决了,发现是解压命令错了,应该是unzip
不过,如果报错如上:E: Unable to locate package xxx
原因:刚安装,软件源还来不及更新,无法找到包
解决办法:
1.首先尝试update命令
sudo apt-get update2.如果不行则执行upgrade
sudo apt-get upgrade3.最后上面两项都不行则尝试
sudo apt-get install aptitude成功以后使用
sudo aptitude install xxx
先使用unzip
解压交叉编译工具链
unzip tools-master.zip
然后,安装交叉编译工具链,并进行配置使它永久有效
先cd到根目录,再输入命令 vi .bashrc
vi .bashrc
快捷键 shift + g 跳到最后一行
另一边先进入解压后的arm-bcm2708文件夹
cd tools-master/arm-bcm2708
一步步获取交叉编译工具链的绝对路径
pwd 打印出来的:
/home/arsen/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
echo $PATH 打印出来的:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708$ ls
arm-bcm2708hardfp-linux-gnueabi arm-rpi-4.9.3-linux-gnueabihf
arm-bcm2708-linux-gnueabi gcc-linaro-arm-linux-gnueabihf-raspbian
arm-linux-gnueabihf gcc-linaro-arm-linux-gnueabihf-raspbian-x64
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708$ cd gcc-linaro-arm-linux-gnueabihf-raspbian-x64
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64$ ls
arm-linux-gnueabihf bin lib libexec share
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64$ cd bin
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin$ pwd
/home/arsen/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
arsen@ubuntu:~/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin$
接着,回到配置窗口,在最后一行加上(第二句的路径是echo $PATH 获取的 + pwd 获取的)
export PATH=$PATH:/home/arsen/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
#或者下面这句,二选一就行
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/:/home/arsen/SYSTEM/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
配置好后,返回操作目录,使用下面命令进行加载
source .bashrc
检查工具链版本,成功运行则安装完毕
arm-linux-gnueabihf-gcc -v
最后,进入SYSTEM文件夹,对内核源码压缩包进行解压
cd SYSTEM
unzip linux-rpi-4.19.y.zip
解压完毕,准备工作完成
二、树莓派等芯片带操作系统的启动过程
1.x86、Intel、windows等设备的启动过程
启动过程:
- 电源 —> BIOS —> windows内核 —> C,D盘的启动 —> 程序的启动(例如QQ的启动)
2.嵌入式产品(树莓派、mini2440、mini6410、nanopi、海思、RK(瑞芯微) )的启动过程
启动过程:
- 电源 —> BootLoader (引导操作系统启动) —> linux内核 —> 文件系统(根据功能性来组织文件夹,带访问权限)—> 嵌入式产品的启动(例如KTV点歌机,人脸识别打卡机,智能家居主控)
3.安卓操作系统的启动过程
启动过程:
- 电源 —> fastBoot/Bootloader/ —> linux内核 —> 文件系统 —> 虚拟机 —> HOME应用程序 —> 点击某图标打开某app
4.小扩展
C51、STM32(裸机,不带操作系统)的开发流程
- 不带操作系统的裸机开发是C语言直接操控底层寄存器实现相关业务
BootLoader开发:
- 一阶段:让CPU跟内存,FLASH,串口,IIC,IIS,数据段等打交道(汇编和C结合驱动这些设备)
- 二阶段:引导Linux内核启动(纯C操作)
三、树莓派Linux内核源码简单认知
linux_530">1.linux内核认知
-
linux是一个开源的,支持多架构多平台代码;
如ARM:海思,树莓派,RK,nanoPi,友善之臂;X86;PowerPC,MIPS
-
可移植性非常高
-
linux内核大约由1.3w个C文件组成,1100w行代码左右;
但是linux内核编译出来一般就是几M,一般是4M左右;
因为是支持多平台多架构,所以在编译之前是需要进行配置的,配置成适合的目标平台来用
2.Linux文件系统分区
详细分区传送门
上图Linux文件都是根据功能来放的
- dev: 放的是设备相关,
- lib: 放的是各种动态库和静态库,
- proc: 放的是内核的数据信息,
- home:是用户登录的工作界面,
- opt: 是跟内核底层有关的,
- sbin: 通常是可执行文件或指令,
- bin: 也是指令和可执行文件,
- boot: 是启动要加载的配置等等。
四、树莓派Linux内核源码配置
1.内核源码配置原因
操作树莓派需要进行驱动代码的编写,编写完后,代码运行需要进行驱动代码的编译,而驱动代码的编译需要一个提前编译好的内核,编译内核必须要进行内核源码的配置。
(配置的最终目标会生成 .config文件,该文件指导Makefile去把有用东西组织成内核)
2.内核源码配置方法
Linux内核源码配置,其实就是配置config
-
linux源码中有很多工程:
树莓派1的工程是bcmrpi_defconfig;
树莓派2、3的工程是bcm2709_defconfig树莓派4的工程是bcm2711_defconfig(临时ChatGPT查的)
2.1 cp 厂家.config
使用厂家源码中的工程文件,进行cp 厂家.config
先进入树莓派Linux内核源码文件夹,然后运行下面指令,查看各个架构的工程文件
find . -name *_defconfig
树莓派3的工程文件
使用下面命令获取bcm2709_defconfig的配置到 .config里
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
命令解释:
#命令解释
ARCH=arm(指定当前要编译的是arm架构)
CROSS_COMPILE=arm-linux-gnueabihf- (指定编译器是树莓派交叉编译工具链)
KERNEL=kernel7 (指明kernel类型,树莓派1设置为kernel,树莓派2,3设置为kernel7,树莓派4设置为kernel7l)
make bcm2709_defconfig(make为配置命令)
在执行该命令的过程了我遇到了两次报错
第一次报错:
YACC scripts/kconfig/zconf.tab.c
/bin/sh: 1: bison: not found
scripts/Makefile.lib:196: recipe for target ‘scripts/kconfig/zconf.tab.c’ failed
make[1]: *** [scripts/kconfig/zconf.tab.c] Error 127
Makefile:534: recipe for target ‘bcm2709_defconfig’ failed
make: *** [bcm2709_defconfig] Error 2解决方法:
根据报错信息来看,这是由于缺少bison工具导致的错误。bison是用于生成解析器的工具,需要进行安装才能继续进行编译过程。
在树莓派上安装bison的方法可以尝试以下命令:
sudo apt-get install bison
第二次报错:
YACC scripts/kconfig/zconf.tab.c
LEX scripts/kconfig/zconf.lex.c
/bin/sh: 1: flex: not found
scripts/Makefile.lib:188: recipe for target ‘scripts/kconfig/zconf.lex.c’ failed
make[1]: *** [scripts/kconfig/zconf.lex.c] Error 127
Makefile:534: recipe for target ‘bcm2709_defconfig’ failed
make: *** [bcm2709_defconfig] Error 2解决方法:
根据报错信息,这次报错是由于缺少flex工具导致的。flex是用于生成词法分析器的工具,需要进行安装才能继续进行编译过程。
在树莓派上安装flex的方法可以尝试以下命令:
sudo apt-get install flex
2.2 make menuconfig 通过菜单一项项配置(通常是基于厂家的config来配置)
通过make menuconfig 一项项的来配置,通常都是基于厂家的config来进行配置。
通过这样的"裁剪",可以减小内核的体积。
先安装一些必要的库
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
安装好后,运行下面指令,在内核菜单进行配置
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
选项解释
- General setup —>(通用选项)
- [ * ] Enable loadable module support —> 内核模块选项
- [ * ]Enable the block layer —> 块设备逻辑层选项(大文件支持、分区、I/O调度)
- System Type —>(平台选项)
- Bus support —> 总线选项
- Kernel Features —>内核特征
- Boot options —> 引导选项
- CPU Power Management —> CPU电源管理选项
- Floating point emulation —> 浮点运算
- Userspace binary formats —> 用户程序格式
- Power management options —> 电源管理选项
- [*] Networking support —> 网络协议选项
- Device Drivers —> 设备驱动
- Firmware Drivers ---- 驱动固件选项
- File systems —> 文件系统选项
- Kernel hacking —> 内核调试选项
- Security options —> 安全模块选项
选择要配置的文件,使用空格可以切换[ ]里面的模式。
[*]:编译进内核(*代表Y,编译进内核,zImage包含了驱动) [M]:编译成模块(以模块的方式生成驱动文件xxx.ko,系统启动后,通过命令inmosd xxx.ko来加载驱动,也可以减小一些内核大小) [ ]:表示不需要的部分 空格可切换修改。 修改完毕后,保存退出
2.3 完全自己来(略)
xxxx
linux__733">五、树莓派 linux 内核源码编译并运行
1.编译
运行下面指令进行编译
编译的时间会比较久(看电脑配置,20~30分钟少不了)
编译过程中如果跑了几分钟没有报错,那就是没问题,等就行了
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
命令解释:
#命令解释
ARCH=arm(指定当前要编译的是arm架构)
CROSS_COMPILE=arm-linux-gnueabihf- (指定编译器是树莓派交叉编译工具链)
KERNEL=kernel7 (指明kernel类型,树莓派1设置为kernel,树莓派2,3设置为kernel7,树莓派4设置为kernel7l)
make -j4:指定用多少电脑资源进行编译(j4是四核的意思,这个要每个人根据自己的电脑的配置以及虚拟机的设置的核数来决定,我之前虚拟机设置的是4核)
zImage:生成内核镜像
modules:要生成驱动模块
dtbs:生成配置文件
编译过程中,我一下子就遇到了一个报错:
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: No such file or directory
#include <openssl/bio.h>
^~~~~~~~~~~~~~~
compilation terminated.
scripts/Makefile.host:90: recipe for target ‘scripts/extract-cert’ failed
make[1]: *** [scripts/extract-cert] Error 1
make[1]: *** Waiting for unfinished jobs…
UPD include/generated/asm-offsets.h
CALL scripts/checksyscalls.sh
Makefile:1073: recipe for target ‘scripts’ failed
make: *** [scripts] Error 2解决方法:
根据报错信息来看,这是由于缺少openssl库导致的错误。缺少openssl/bio.h头文件。
在树莓派上安装openssl库的方法可以尝试以下命令:
sudo apt-get install libssl-dev
解决后再运行编译命令就一直跑了,应该没问题了,等待就好
编译完成
编译成功后,会生成vmlinux文件,失败则无此文件
2.将zmage文件打包成树莓派可用的xxx.img镜像文件
生成的zImage文件在/home/arsen/SYSTEM/linux-rpi-4.19.y/arch/arm/boot
路径的boot文件夹下
回到内核源码目录,输入下面命令进行镜像打包(会生成kernel_new.img适合树莓派使用的镜像文件)
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
3.将树莓派SD卡的U盘映射到虚拟机
将插有树莓派SD卡的U盘插入电脑,通过下面操作,把U盘映射到ubuntu虚拟机(U盘插入过程中,电脑有时会自动识别到并询问是否进行映射,问题不大,可自行百度解决)
输入下面命令,查看内核信息(可以显示系统中各种硬件设备的信息),有设备接入的时候内核会打印出驱动层面的信息
dmesg
看到sb1,sb2,则说明接入成功
sdb1,2分别是树莓派sd卡的两个分区(sd卡在刷树莓派镜像的时候会自动变成两个分区)
- ①一个fat分区,是boot相关的内容,kernel的img文件在此分区。
- ②一个是ext4分区,也就是系统的根目录分区。(
cd /
进入的就是系统的根目录)
4.数据拷贝
4.1 挂载U盘
返回到原先创建SYSTEM目录的地方,再创建data1和data2两个文件夹
运行下面指令,将两个分区挂载到新创建的两个数据文件夹
sudo mount /dev/sdb1 data1 #挂载U盘的sdb1文件分区到当前路径下的data1文件夹, #该分区为fat分区,是boot相关的内容,kernel的img.
sudo mount /dev/sdb2 data2 #挂载U盘的sdb2文件分区到当前路径下的data2文件夹,#该分区为ext4分区,也就是系统的根目录分区.
运行完后,两个新建的文件夹就都有数据了,都分别关联到了两个分区
data1为fat分区(boot相关),data2为ext4分区(系统根目录相关)一定要对应好!!!
4.2 安装modules
运行指令安装,因为内核配置时,有一部分是编译成模块的形式配置进来的,安装后hdmi接口、usb、wifi、io口等等的设备才能使用,所以需要这么一步。
回到内核源码文件夹,运行安装命令
# 操作ext4分区需要root权限,sudo
# [ext4]为第二分区(sdb2)虚拟机上挂载的地址(data2的位置),需要根据自己的地址更改
# 更改前
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4] modules_install
# 更改后,我的,注意将代码的“[ext4]”更改为data2的绝对路径 !!
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/arsen/data2 modules_install
安装完成
4.3 安装并更新kernel.img文件
注意查看原来镜像名字是kernel7.img
ls /home/arsen/data1
在操作过程中,原来的这个kernel7.img会被覆盖,为了防止刷机失败,或者拷贝过程中文件损坏,需要提前用别名备份这个文件。
打开新的终端(ctrl alt t)(方便操作罢了),进入其存放路径(cd /home/data1)
sudo cp kernel7.img kernel7OLD.img
从内核源码目录(linux-rpi-4.19.y
)拷贝kernel_new.img
(是由zImage打包而成)到data1并且命名为kernel7.img
覆盖原来的文件
sudo cp kernel_new.img /home/arsen/data1/kernel7.img
检查拷贝是否有问题,使用命令md5sum
显示文件的唯一编码号,若相同则为同一个文件
- md5sum kernel_new.img
- md5sum /home/arsen/data1/kernel7.img
4.4 拷贝相关配置文件
从内核源码目录linux-rpi-4.19.y
进行拷贝,这些配置文件是为了能够加载驱动以及一些其他的配置
# 修改前,[fat]为第一分区(sdb1)虚拟机上挂载的地址(data1的位置),需要根据自己的地址更改
cp arch/arm/boot/dts/.*dtb* [fat]/
cp arch/arm/boot/dts/overlays/.*dtb* [fat]/overlays/
cp arch/arm/boot/dts/overlays/README [fat]/overlays/
# 按自己需求修改后,README是说明书
cp arch/arm/boot/dts/.*dtb* /home/arsen/data1/
cp arch/arm/boot/dts/overlays/.*dtb* /home/arsen/data1/overlays/
cp arch/arm/boot/dts/overlays/README /home/arsen/data1/overlays/
5.在树莓派上运行编译好的内核镜像
5.1 USB-TTL进行串口打印调试信息,观看启动过程
先点击选择断开连接sd卡,使其重新挂载在windows上
添加USB串口信息,如果之前在做别的项目,例如串口编程时,会把这个配置信息删掉,这时需要添加回来
配置好后,sd卡插回树莓派,USB-TTL连接,用MobaXterm进行串口连接,可以看到启动正常。
此时,可以再输入查看内核版本的命令进行确认(如果和之前不一样,则说明更换成功)
uname -r
uname -a
5.2 SSH连接查看
用指令uname -r/a
查看内核版本,发现内核版本与之前相比,已然发生了变化,说明更换成功
我这边用的是SSH连接,内核更换后,我发现之前的wifi配置信息还是有效的,就直接通过MobaXterm进行SSH连接树莓派了