内核的安装可以轻易地通过像 apt
这样的包管理器来处理。通过添加特定的仓库,你能很轻易地安装实验版本的或者指定版本的内核(比如针对音频产品的实时内核)。apt安装的内核是发行版并且是已经编译好的?这里下载的不是发行版并且是源码?是这样吗?求大佬告知。
考虑一下,既然升级内核如此容易,为什么你不愿意自行编译一个呢?这里列举一些可能的原因:
- 你想要简单了解编译内核的过程
- 你需要启用或者禁用内核中特定的选项,因为它们没有出现在标准选项里
- 你想要启用标准内核中可能没有添加的硬件支持
- 你使用的发行版需要你编译内核
- 你是一个学生,而编译内核是你的任务
不管出于什么原因,懂得如何编译内核是非常有用的,而且可以被视作一个通行权。当我第一次编译一个新的 Linux 内核(那是很久以前了),然后尝试从它启动,我从中(系统马上就崩溃了,然后不断地尝试和失败)感受到一种特定的兴奋。
既然这样,让我们来实验一下编译内核的过程。我将使用 Ubuntu 16.04 Server 来进行演示。在运行了一次常规的 sudo apt upgrade
之后,当前安装的内核版本是 4.4.0-121
。我想要升级内核版本到 4.17
, 让我们小心地开始吧。
一、下载linux内核源码到/usr/src/
1.下载最新版本的内核
进入 Linux 内核官网 https://www.kernel.org/ 下载 Linux 内核 , 点击右侧 黄色的 " Latest Release "
在这里插入图片描述
按钮 , 下载最新的 Linux 内核发布版本 ;
最新版的 Linux 内核有 122MB ;
2.下载指定版本的内核
目标 : 下载5.6.14版本的 Linux 内核 ;
- 主版本号 :5
- 此版本号 :6
- 小版本号 ( 修改次数 ) :14
在 Linux 内核 官网 https://www.kernel.org/ 页面中 , 点击 https://www.kernel.org/pub/ 链接 ,
进入 Linux 内核 public 页面 , 进入 https://mirrors.edge.kernel.org/pub/ 页面 ,
点击 linux 目录 , 进入 https://mirrors.edge.kernel.org/pub/linux/ 页面 ,
点击 kernel 链接 , 进入 https://mirrors.edge.kernel.org/pub/linux/kernel/ 页面 ,
选择 v5.x 版本 , 进入 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/ 页面 , 在该界面中可以直接下载 linux-5.6.14.tar.gz 文件 , 这就是5.6.14版本 Linux 内核源码 ;
3.git获取
从Git仓库克隆是一种更灵活更高效的方法,适合于想要获取新版本或历史的Linux内核源码,并且可以跟踪更新和修改的用户。具体操作如下:
1. 打开终端,切换到你想要存放Linux内核源代码的目录下,例如/usr/src/。
2. 输入以下命令,从Git仓库克隆Linux内核源代码:
3. git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
4. 克隆完成后,你就可以在该目录下看到一个名为linux的文件夹,这就是Linux内核源代码的根目录。
5. 切换到某个特定版本的Linux内核源码,输入该命令,查看所有可用的标签(tag):git tag
6. 切换到你想要的标签,例如v5.15.7:git checkout v5.15.7
7. 跟踪新的更新和修改,输入该命令,切换到主分支(master):git checkout master
8. 拉取新的提交(commit):git pull。
4.Linux内核版本号的含义
以 5.6.14版本为例 :
- 主版本号 :5
- 次版本号 :6
- 小版本号 ( 修改次数 ) :14
版本稳定性 :
- 稳定版本 : 次版本号为偶数 , 说明该版本的 Linux 内核是可以使用的稳定版本 ,
- 不稳定版本 : 如果次版本号为奇数 , 说明在该版本中 , 添加了新的模块 , 不能保证稳定性 , 如
5.7.14就是不稳定版本 。
5.查看当前使用的内核版本
① 使用uname命令是一种简单快捷的方法,适合于想要快速查看当前运行中的Linux内核版本的用户。具体操作如下:
打开终端,输入以下命令,查看当前运行中的Linux内核版本:
uname -r
输出结果类似于以下内容:
5.15.7-200.fc35.x86_64
当前运行的Linux内核版本是5.15.7,编译配置为200.fc35.x86_64。不同的发行版可能有不同的配置和后缀,但是前面的数字部分是通用的,表示Linux内核的主版本号、次版本号和修订号。
② 查看/proc/version文件是一种更详细更完整的方法,适合于想要查看当前运行中的Linux内核版本以及编译信息的用户。具体操作如下:
打开终端,输入以下Linux常用命令,查看/proc/version文件的内容:
cat /proc/version
输出结果类似于以下内容:
Linux version 5.15.7-200.fc35.x86_64 (mockbuild@bkernel01.iad2.fedoraproject.org) (gcc (GCC) 11.2.1 20210728 (Red Hat 11.2.1-1), GNU ld version 2.37-10.fc35) #1 SMP Wed Dec 8 14:29:02 UTC 2021
表示当前运行中的Linux内核版本是5.15.7,编译配置200.fc35.x86_64,编译器gcc 11.2.1,链接器GNU ld 2.37,编译时间2021年12月8日14:29:02。
③dmesg(dmesg | grep "Linux version")命令
6.解压源码到/usr/src/中
在新下载的内核所在的文件夹下,使用该命令来解压内核:
tar xvzf linux-4.17-rc2.tar.gz -C /usr/src
使用命令 cd linux-4.17-rc2
进入新生成的文件夹。
二、安装所需要的环境
为了编译内核,我们首先得安装一些需要的环境。这可以通过一个命令来完成:
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
三、配置内核代码
在编译内核之前,我们可以对内核源代码进行配置。配置的目的主要是确定哪些模块会编译到内核当中。
①进入源代码目录
cd linux-5.9.6
②从当前机器的启动目录拷贝配置信息到源代码目录。这步操作的意思是我们编译内核的配置采用用当前环境一致的配置。
cp -v /boot/config-$(uname -r) .config
然后执行./.config,
也可以选择最快的原版的配置(默认)方式
root@shana:/usr/src/linux-source-2.6.22# make oldconfig
③也可以通过如下命令启动配置界面
make menuconfig
该命令将打开一个配置工具(图 1),它可以让你遍历每个可用模块,然后启用或者禁用你需要或者不需要的模块。下面是打开的配置界面。可以看出里面包含所有的内核组件,包括文件系统,网络,IO栈,虚拟化和设备驱动等等。如果你不熟悉,可以不做任何修改。
很有可能你会禁用掉内核中的一个重要部分,所以在 menuconfig
期间小心地一步步进行。如果你对某个选项不确定,不要去管它。或者更好的方法是使用我们拷贝的当前运行的内核的配置文件(因为我们知道它可以工作)。一旦你已经遍历了整个配置列表(它非常长),你就准备好开始编译了。
四、编译和安装内核
①通过如下命令就可以编译内核了
make
make -j 10
上面参数是并发数量,通常可以是CPU核心数的2倍。好像容易出问题。
②安装那些之前启用的模块
sudo make modules_install
执行结束之后,会在/lib/modules下生成新的目录/lib/modules/2.6.32.10-generic/,其中的build就是内核树。在以后编译模块时要用到。
③安装内核
sudo make install
④启用内核作为引导
一旦 make install
命令完成了,就是时候将内核启用来作为引导。使用这个命令来实现:
sudo update-initramfs -c -k 4.17-rc2
当然,你需要将上述内核版本号替换成你编译完的。当命令执行完毕后,使用如下命令来更新 grub:
sudo update-grub
现在你可以重启系统并且选择新安装的内核了。
注:一下两个链接是如何切换内核的方法,没有试过。可以试试告诉我哪个好用。
ubuntu如何进行切换内核版本全教程_ubuntu切换内核版本-CSDN博客
Re:Linux内核编译很简单,6步编译一个自己的内核-linux内核编译方法
五、编译2.6.32.10内核源码时遇到的一些问题
1.error: code model kernel does not support PIC mode
这是由于不支持地址无关模式,在 Makefile这段的最后加上-fno-pie
即可
344 KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
345 -fno-strict-aliasing -fno-common \
346 -Werror-implicit-function-declaration \
347 -Wno-format-security \
348 -fno-delete-null-pointer-checks -fno-pie
或者调查后发现删除删除该模块目录下的.cache.mk文件就好了,重新make即可
2.fatal error: linux/compiler-gcc7.h: No such file or directory
原因: Linux2.6属于老版本内核, 与新版gcc不适配, 直接原因是没有这个文件,只有gcc4和gcc3,于是另外再安装gcc4, 注意无需卸载gcc7, 切换即可
linux下gcc、g++不同版本的安装和切换
①可以通过如下命令查看当前安装的版本:
ll /usr/bin/gcc*
②安装gcc4.8
sudo apt install gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib
③使用update-alternatives设置gcc和g++:
update-alternatives是ubuntu系统中专门维护系统命令链接符的工具,通过它可以很方便的设置系统默认使用哪个命令、哪个软件版本。 其中40
,50
,70
是优先级数值可以自己设定,--slave
能保证gcc和g++保持相同的版本。
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 50 --slave /usr/bin/g++ g++ /usr/bin/g++-7
④使用如下命令选择gcc的版本:
sudo update-alternatives --config gcc
可以看到当前gcc默认的版本是gcc-7,下面我们修改为gcc-4.8,直接选择编号即可。
$ sudo update-alternatives --config gcc
There are 3 choices for the alternative gcc (providing /usr/bin/gcc).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/gcc-7 70 auto mode
1 /usr/bin/gcc-4.8 40 manual mode
2 /usr/bin/gcc-5 50 manual mode
3 /usr/bin/gcc-7 70 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/bin/gcc-4.8 to provide /usr/bin/gcc (gcc) in manual mode
⑤验证是否成功
gcc -v/g++ -v
⑥删除某个gcc版本
sudo update-alternatives --remove gcc /usr/bin/gcc-4.5
再使用apt-remove
删除即可
Re:linux下gcc、g++不同版本的安装和切换-腾讯云开发者社区-腾讯云
3.安装gcc4.8时出现E:Package make has no installation candidate
ubuntu20.04的默认软件源没有这个gcc4.8的包,加入即可
则在/etc/apt/sources.list
中添加以下两个源
deb http://dk.archive.ubuntu.com/ubuntu/ xenial main
deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe
然后更新即可。
sudo apt-get update
sudo apt-get upgrade
Re:Ubuntu18安装gcc-4.8_ubuntu安装gcc4.8-CSDN博客
bash - GCC version 4.9 has no installation candidate - Stack Overflow
4. gcc: error: elf_x86_64: No such file or directory
错误原因:
由于gcc 4.6不再支持linker-style架构。
解决办法:
将arch/x86/vdso/Makefile中,以VDSO——LDFLAGS_vso.lds开头所在行的“-m elf_x86_64”替换成“-m64”
将VDSO_LDFLAGS_vdso32.lds开头所在行的“-m elf_x86”替换成“-m32”。
确保当前路径是在内核目录中,然后执行命令:
vim usr/src/linux-2.6.32.10/arch/x86/vdso/Makefile
,在Makefile中搜索elf_x86_64,然后把"-m elf_x86_64"替换为"-m64";接着在Makefile中搜索elf_i386,然后把"-m elf_i386"替换为"-m32",保存退出,问题解决了。接着继续编译,就可以了。
Re:elf_i386或elf_x86_64:没有那个文件或目录 解决方法 | 说好一起走
5.make[1]: *** [kernel/timeconst.h] Error 255
根据提示将相应文件中的相应行的 defined()
删除即可。
将kernel/timeconst.pl中第373行的defined()去掉只留下@val就可以了。
6.重复的成员'page'错误
在编译Linux-2.6.33内核时,出现的了一个错误就是:重复的成员‘page’,这个是由于gcc的版本较高造成的。
a、按照错误的指示,错误的代码是在drivers/net/igbvf/igbvf.h文件的第129行。
b、打开文件,看129行,代码为:struct page *page;再往上看,第124行,也有struct page *page;这行代码,这个结构定义在内部的一个结构体中。就是他的名字与129行的重复了,而4.6.3的编译器不支持这种方式的定义,我们修改129行的代码为struct page *pagep;保存退出。
7.fatal error: linux/config.h: No such file or directory
進行內核模塊的編譯時,因為包含了#include <linux/config.h>,出現include的linux下沒有config.h這個文件錯誤提示:
fatal error: linux/config.h: No such file or directory
原因與解決方法:
現在較新的內核已經棄用了config.h,把這個文件新建上去即可。執行命令(注意路徑的不同):
$sudo vim /usr/src/linux-source-2.6.38/include/linux/config.h
輸入如下內容:
#ifndef _LINUX_CONFIG_H
#define _LINUX_CONFIG_H
#endif
保存後退出重新編譯,OK!
Re:Linux內核編譯錯誤fatal error: linux/config.h: No such file or_Linux內核
Re:https://www.cnblogs.com/QiQi-Robotics/p/15229668.html
六、加载内核模块时遇到的问题
1..c文件中有#include <linux/module.h>但编译时说找不到该文件
Ubuntu不自己带内核的源码的,需要你把内核源码下载解压到ur/src/里。
还有一种可能是找的头文件路径不对。
2.insmod: ERROR: could not insert module module.ko: Invalid parameters的几个原因
①insmod之后再次对该模块进行加载时会报错,这个主要是因为模块的printk打印的信息不能直接显示在终端上,可以使用 dmesg 查看自开机以来的信息就可以看到printk输出的信息了,使用dmesg | tail可以查看最后的几个消息。使用rmmod 可以移除安装了的模块。
②编译.ko时的内核版本与当前系统运行的内核版本不一致;编译模块时选择的Linux头文件目录与当前运行的系统版本不匹配,使用命令:uname -r查看当前运行的内核版本,然后选择正确的Linux头文件路径,也可以下载和机器内核对应的Linux源码,这样指定Linux头文件目录到指定的源码目录就行了。即修改.ko所在路径中的makefile的KERNELDIR为当前系统的内核版本的头文件路径,或者将当前系统内核切换为编译ko文件时使用的内核版本。
③生成的模块名字不能以module命名,改成其他名字就好了
3.ubuntu没有/var/log/messages系统日志文件
在ubuntu系统中,有时候,我们需要通过journalctl -xe来查看服务启动日志,但是这个日志打印不全,所以还是需要通过/var/log/messages这个文件来看。
在一些新的ubuntu系统中,这个文件是不存在的,我们需要设置,修改文件/etc/rsyslog.d/50-default.conf
我们可以看到,为什么messages文件在/var/log目录下没有,因为被注释掉了,我们根据需要开启,或者新增一行配置即可:
*.info;mail.none;authpriv.none;cron.none /var/log/messages
保存该配置文件,然后无需重启系统,只需要重启rsyslog这个服务即可。
systemctl restart rsyslog.service
我们最后来看看效果:
最后成功开启了messages日志文件,我们也看到了系统日志。以后查看详细的日志都可以在这里面查看。
Re:ubuntu系统没有/var/log/messages系统日志文件解决办法_ubuntu messages-CSDN博客
七、关于内核树
1.系统自带的内核树
有时,安装的系统已经自带了Linux内核树
,足够用来编译驱动程序了。
自带的内核树通常位于
/lib/modules/<系统内核版本>/build
其中,系统内核版本可以用uname -r
来查看
$ uname -r
5.11.0-41-generic
2.环境配置
初次配置内核树要先安装一些必要的环境
sudo apt-get build-dep linux linux-image-$(uname -r)
如果报错Error :: You must put some ‘source‘ URIs in your sources.list
,请参照这里)
除了上面的环境之外,还要安装这
sudo apt-get install libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf dwarves
3.构建内核和安装模块
为了防止make
中的make modules_install
环节失败, 请先运行下面的命令
sudo scripts/config --set-str SYSTEM_TRUSTED_KEYS ""
最后,把模块安装到/lib/modules/$(uname -r)
目录(由内核的makefile指定路径)
Re: