树莓派linux内核源码编译
Raspberry Pi 内核 托管在 GitHub 上;更新滞后于上游 Linux内核,Raspberry Pi 会将 Linux 内核的长期版本整合到 Raspberry Pi 内核中。
1 构建内核
操作系统随附的默认编译器和链接器被配置为构建在该操作系统上运行的可执行文件。原生编译使用这些默认编译器和链接器。交叉编译是为运行编译过程的目标之外的目标编译代码的过程。Raspberry Pi 内核的交叉编译允许从 32 位操作系统构建 64 位内核,反之亦然。也可以从 Raspberry Pi 以外的设备交叉编译 32 位或 64 位 Raspberry Pi 内核。
1.1 下载内核源代码
下载最新 Raspberry Pi 内核的源代码:
git clone --depth=1 https://github.com/raspberrypi/linux
上面的 git clone 命令下载的是当前活动分支,从这个分支构建 Raspberry Pi 操作系统镜像,没有任何历史记录。省略 --depth=1可以下载整个版本库,包括所有分支的完整历史。
要下载不带历史记录的不同分支,在上述命令中添加 --branch 选项,并将 替换为要下载的分支名称
bashgit clone --depth=1 --branch <branch> https://github.com/raspberrypi/linux
1.2 原生构建内核
1.2.1 安装编译依赖项
sudo apt install bc bison flex libssl-dev make
1.2.2 构建配置
在构建内核时应用默认配置。准备默认配置,需要根据 Raspberry Pi 型号运行相应命令,这里使用的是树莓派5,命令为:
cd linux
KERNEL=kernel_2712
make bcm2712_defconfig
1.2.3 使用 LOCALVERSION 自定义内核版本
为防止内核覆盖 /lib/modules
中的现有模块,并在 uname
输出中说明运行的是自己的内核,调整 LOCALVERSION
。
修改 .config
中的以下一行:
CONFIG_LOCALVERSION="-v7l-MY_CUSTOM_KERNEL"
1.2.4 构建
构建内核。这一步可能需要很长时间, 取决于 Raspberry Pi 型号:
# 构建 64 位内核
make -j6 Image.gz modules dtbs# 构建 32 位内核
make -j6 zImage modules dtbs
1.2.5 安装内核
将内核模块安装到启动媒体上:
sudo make -j6 modules_install
然后,将内核和设备树 blobs 安装到启动分区中,并备份原始内核。
如果不想在运行此命令的 Raspberry Pi 上安装刚编译好的内核,可将编译好的内核复制到另一个启动介质的启动分区,而不是 /boot/firmware/。
- 安装 64 位内核:
# 运行以下命令创建当前内核的备份镜像,安装新的内核镜像、覆盖层、README,并卸载分区
sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img
sudo cp arch/arm64/boot/Image.gz /boot/firmware/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware/$KERNEL-backup.img
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/
- 安装 32 位内核:
# 创建当前内核的备份,然后安装新的内核映像
sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img
sudo cp arch/arm/boot/zImage /boot/firmware/$KERNEL.img# 根据内核版本,运行以下命令
# 对于版本 6.4 以下的内核:
sudo cp arch/arm/boot/dts/*.dtb /boot/firmware/
# 适用于 6.5 及以上版本的内核:
sudo cp arch/arm/boot/dts/broadcom/*.dtb /boot/firmware/# 复制覆盖层和 README
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/firmware/overlays/
- 运行以下命令重启 Raspberry Pi 并运行新编译的内核
sudo reboot
1.3 交叉编译内核
首先需要准备一台合适的 Linux 交叉编译主机,这里使用的是 ubuntu。
1.3.1 安装所需的依赖项和工具链
sudo apt install bc bison flex libssl-dev make libc6-dev libncurses5-dev# 安装 64 位工具链以构建 64 位内核,请运行以下命令
sudo apt install crossbuild-essential-arm64# 安装 32 位工具链以构建 32 位内核,请运行以下命令
sudo apt install crossbuild-essential-armhf
1.3.2 编译配置
在构建内核时应用默认配置。准备默认配置,需要根据 Raspberry Pi 型号运行相应命令,这里使用的是树莓派5,命令为:
cd linux
KERNEL=kernel_2712
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2712_defconfig
1.3.3 使用 LOCALVERSION 自定义内核版本
为防止内核覆盖 /lib/modules
中的现有模块,并在 uname
输出中说明运行的是自己的内核,调整 LOCALVERSION
。
修改 .config
中的以下一行:
CONFIG_LOCALVERSION="-v7l-MY_CUSTOM_KERNEL"
1.3.4 构建
- 构建 64 位内核
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 映像模块 dtbs
- 构建 32 位内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage 模块 dtbs
1.3.5 安装内核
构建内核后,需要将其复制到 Raspberry Pi 的启动媒体(可能是 SD 卡或 SSD)上并安装模块。
- 查找启动媒体
首先,运行 lsblk。然后,连接启动媒体。再次运行 lsblk;新设备代表启动媒体
例如我这里的输出为:
sdbsdb1sdb2
将这些分区挂载为 mnt/boot 和 mnt/root,调整分区代号以匹配启动媒体的位置:
mkdir mnt
mkdir mnt/boot
mkdir mnt/root
sudo mount /dev/sdb1 mnt/boot
sudo mount /dev/sdb2 mnt/root
- 安装
将内核模块安装到启动媒体上:
# 对于 64 位内核
sudo env PATH=$PATH make -j12 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=mnt/root modules_install# 对于 32 位内核
sudo env PATH=$PATH make -j12 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/root modules_install
- 将内核和设备树 blob 安装到启动分区,并备份原始内核
# 安装 64 位内核
sudo cp mnt/boot/$KERNEL.img mnt/boot/$KERNEL-backup.img
sudo cp arch/arm64/boot/Image mnt/boot/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* mnt/boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README mnt/boot/overlays/
sudo umount mnt/boot
sudo umount mnt/root# 安装 32 位内核
sudo cp mnt/boot/$KERNEL.img mnt/boot/$KERNEL-backup.img
sudo cp arch/arm/boot/zImage mnt/boot/$KERNEL.img
# 对于版本 6.4 以下的内核
sudo cp arch/arm/boot/dts/*.dtb mnt/boot/
# 6.5 及以上版本的内核
sudo cp arch/arm/boot/dts/broadcom/*.dtb mnt/boot/sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README mnt/boot/overlays/
sudo umount mnt/boot
sudo umount mnt/root
最后,将启动媒体连接到 Raspberry Pi 并接通电源,运行新编译的内核。
2 配置内核
Linux 内核是高度可配置的, 以便根据自己的需要进行定制,例如启用新的或试验性的网络协议,或启用对新硬件的支持。最常见的配置方法是通过 make menuconfig 界面完成, 也可以手动修改你的 .config
文件:
2.1 准备配置
menuconfig 工具需要 ncurses 开发头文件才能正常编译:
sudo apt install libncurses5-dev
接下来,下载内核源代码。
2.2 menuconfig
编译并运行 menuconfig 工具:
make menuconfig# 交叉编译 64 位内核:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
# 交叉编译 32 位内核:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
简短编译后,menuconfig 将显示包含所有可配置选项的子菜单列表。第一次尝试时,不要轻易启用或禁用很多选项;这样很容易破坏配置。
3 内核补丁
在构建自定义内核时,可能希望在 Linux 内核中应用补丁或补丁集(patchsets)。
3.1 确定内核版本
查看设备上当前运行的内核版本:
uname -r
# 6.6.51+rpt-rpi-2712
在打补丁之前,务必检查内核版本。在内核源代码目录下,运行以下命令查看内核版本:
head Makefile -n n# 类似下面的输出:
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 38
EXTRAVERSION =
NAME = Pinguïn Aangedreven
这里可以看到版本为 6.1.38。
3.2 应用补丁
补丁的应用取决于补丁的发布格式。开发者会以单个文件的形式发布大多数补丁。使用 patch 工具来打补丁。
以下命令将下载、解压缩并使用实时内核补丁:
wget https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/patch-6.1.38-rt13-rc1.patch.gz
gunzip patch-6.1.38-rt13-rc1.patch.gz
cat patch-6.1.38-rt13-rc1.patch | patch -p1
有些开发者会以 邮箱格式 发布补丁,即一个包含多个补丁文件的文件夹。使用 Git 可以打上这些补丁:
git am -3 /path/to/patches/*
相关文章:

树莓派linux内核源码编译
Raspberry Pi 内核 托管在 GitHub 上;更新滞后于上游 Linux内核,Raspberry Pi 会将 Linux 内核的长期版本整合到 Raspberry Pi 内核中。 1 构建内核 操作系统随附的默认编译器和链接器被配置为构建在该操作系统上运行的可执行文件。原生编译使用这些默…...

本地小主机安装HomeAssistant开源智能家居平台打造个人AI管家
文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 前言 大家好!今天我要向大家展示如何将一台迷你的香橙派Z…...

SpringBoot返回文件让前端下载的几种方式
01 背景 在后端开发中,通常会有文件下载的需求,常用的解决方案有两种: 不通过后端应用,直接使用nginx直接转发文件地址下载(适用于一些公开的文件,因为这里不需要授权)通过后端进行下载&#…...

人工智能及深度学习的一些题目
1、一个含有2个隐藏层的多层感知机(MLP),神经元个数都为20,输入和输出节点分别由8和5个节点,这个网络有多少权重值? 答:在MLP中,权重是连接神经元的参数,每个连接都有一…...

15-利用dubbo远程服务调用
本文介绍利用apache dubbo调用远程服务的开发过程,其中利用zookeeper作为注册中心。关于zookeeper的环境搭建,可以参考我的另一篇博文:14-zookeeper环境搭建。 0、环境 jdk:1.8zookeeper:3.8.4dubbo:2.7.…...

【Rust自学】8.5. HashMap Pt.1:HashMap的定义、创建、合并与访问
8.5.0. 本章内容 第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构,这些集合可以包含很多值。但是第八章所讲的集合与数组和元组有所不同。 第八章中的集合是存储在堆内存上而非栈内存上的,这也意味着这些集合的数据大小无需在编…...

未来网络技术的新征程:5G、物联网与边缘计算(10/10)
一、5G 网络:引领未来通信新潮流 (一)5G 网络的特点 高速率:5G 依托良好技术架构,提供更高的网络速度,峰值要求不低于 20Gb/s,下载速度最高达 10Gbps。相比 4G 网络,5G 的基站速度…...

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作
近年来,大型语言模型(LLMs)的发展突飞猛进,逐步缩小了与通用人工智能(AGI)的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3,作为一款强大的混合专家模型(Mixture-of-Experts, MoE&a…...

Uniapp在浏览器拉起导航
Uniapp在浏览器拉起导航 最近涉及到要在浏览器中拉起导航,对目标点进行路线规划等功能,踩了一些坑,找到了使用方法。(浏览器拉起) 效果展示 可以拉起三大平台及苹果导航 点击选中某个导航,会携带经纬度跳转…...

公平联邦学习——多目标优化
前言 前段时间接触到了联邦学习(Federated Learning, FL)。涉猎了几年多目标优化的我,惊奇地发现横向联邦学习里面也有用多目标优化来做的。于是有感而发,特此写一篇博客记录记录,如有机会可以和大家多多交流。遇到不…...

奇怪的Python:为何字符串要设置成不可变的?
你好!我是老邓。今天我们来聊聊 Python 中字符串不可变这个话题。 1、问题简介: Python 中,字符串属于不可变对象。这意味着一旦字符串被创建,它的值就无法被修改。任何看似修改字符串的操作,实际上都是创建了一个新…...

Vue-Router之嵌套路由
在路由配置中,配置children import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({mode: history,base: import.meta.env.BASE_URL,routes: [{path: /,redirect: /home},{path: /home,name: home,component: () &…...

MyBatis使用的设计模式
目录 1. 工厂模式(Factory Pattern) 2. 单例模式(Singleton Pattern) 3. 代理模式(Proxy Pattern) 4. 装饰器模式(Decorator Pattern) 5. 观察者模式(Observer Patt…...

arm rk3588 升级glibc2.31到2.33
一、查看glibc版本 rootztl:~# ldd --version ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNE…...

【Linux系列】sed命令的深入解析:如何使用sed删除文件内容
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

C++ 设计模式:桥接模式(Bridge Pattern)
链接:C 设计模式 链接:C 设计模式 - 装饰模式 桥接模式(Bridge Pattern)是一种结构型设计模式,它通过将抽象部分(业务功能)与实现部分(平台实现)分离,使它们…...

MATLAB中whitespacePattern函数用法
目录 语法 说明 示例 匹配空白字符 替换非标准空白 更正错误的间距 whitespacePattern函数的功能是匹配空白字符。 语法 pat whitespacePattern pat whitespacePattern(N) pat whitespacePattern(minCharacters,maxCharacters) 说明 pat whitespacePattern 创建一…...

Django多字段认证的实现
Django多字段认证 需求: django认证的检查用户是username,如果使用 username和 手机号验证登录。 重写: ModelBackend 类下的 authenticate 方法 # 在对应应用下创建 utils.py""" 修改Django认证类,为了实现 …...

【AndroidAPP】权限被拒绝:[android.permission.READ_EXTERNAL_STORAGE],USB设备访问权限系统报错
一、问题原因 1.安卓安全性变更 Android 12 的安全性变更,Google 引入了更严格的 PendingIntent 安全管理,强制要求开发者明确指定 PendingIntent 的可变性(Mutable)或不可变性(Immutable)。 但是…...

SQL进阶技巧:如何分析连续签到领金币数问题?
目录 0 题目需求 1 数据准备 2 问题分析 2.1 代码实现 2.2 代码功能分析 第一段 SQL...

1、ELK的架构和安装
ELK简介 elk:elasticsearch logstash kibana,统一日志收集系统。 elasticsearch:分布式的全文索引引擎的非关系数据库,json格式,在elk中存储所有的日志信息,架构有主和从,最少需要2台。 …...

Vue2/Vue3使用DataV
Vue2 注意vue2与3安装DataV命令命令是不同的Vue3 DataV - Vue3 官网地址 注意vue2与3安装DataV命令命令是不同的 vue3vite 与 Vue3webpack 对应安装也不同vue3vite npm install kjgl77/datav-vue3全局引入 // main.ts中全局引入 import { createApp } from vue import Da…...

汇编环境搭建
学习视频 将MASM所在目录 指定为C盘...

Android 系统 `android.app.Fragment` 类的深度定制与常见问题解析
Android 系统 android.app.Fragment 类的深度定制与常见问题解析 目录 引言Fragment 概述Fragment 的生命周期Fragment 的系统层深度定制 4.1 Fragment 的创建与初始化4.2 Fragment 的布局与视图4.3 Fragment 的通信机制4.4 Fragment 的动画与过渡4.5 Fragment 的状态保存与恢…...

linux ueditor nginx https 后台配置项返回格式出错,上传功能将不能正常使用
jsp的版本 如果出现了这个错误,上传的图标都亮起的情况,还是提示这个, 可以试试修改 uedtior.all.js 8082行 isJsonp utils.isCrossDomainUrl(configUrl); 改为 // isJsonp utils.isCrossDomainUrl(configUrl); isJsonp true; 如果还不…...

【机器学习 | 数据挖掘】时间序列算法
时间序列是按时间顺序排列的、随时间变化且相互关联的数据序列。分析时间序列的方法构成数据分析的一个重要领域,即时间序列分析。以下是对时间序列算法的详细介绍: 一、时间序列的分类 时间序列根据所研究的依据不同,可有不同的分类&#…...

uniapp H5 对接 声网,截图
文章目录 安装依赖创建容器容器样式 javascript代码ImageDataToBlob 方法 控制控制台LOG输出 安装依赖 版本"agora-rtc-sdk-ng": "^4.22.0", 创建容器 <template><view class"videoValue " id"videoValue"><u-toast…...

家谱管理系统|Java|SSM|VUE| 前后端分离
【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库…...

【LeetCode】200、岛屿数量
【LeetCode】200、岛屿数量 文章目录 一、并查集1.1 并查集1.2 多语言解法 二、洪水填充 DFS2.1 洪水填充 DFS 一、并查集 1.1 并查集 // go var sets int var father [90000]intfunc numIslands(grid [][]byte) int {n, m : len(grid), len(grid[0])build(grid, n, m)for i …...

idea报错:There is not enough memory to perform the requested operation.
文章目录 一、问题描述二、先解决三、后原因(了解) 一、问题描述 就是在使用 IDEA 写代码时,IDEA 可能会弹一个窗,大概提示你目前使用的 IDEA 内存不足,其实就是提醒你 JVM 的内存不够了,需要重新分配。弹…...