linux 内核编译

mx_jun 2024-10-03 16:37:07 阅读 77

目录

Linux操作系统框架

Linux内核的主要功能:

Linux的内核目录结构:

结构图: 

详细介绍: 

uname - a 补充

编译之前

UTC 时间补充

Linux内核编译流程:

方法一:  官方内核编译:

1. 运行 build.sh 脚本, 记得加 sudo 权限

2. 选择 Kernel package, 然后回车 

3. 然后会提示是否需要显示内核配置界面

4. 接着选择开发板的型号 

编译完成

5. 查看编译生成的内核相关的 deb 包 --  生成在这个 output/debs/  路径下

解压  linux-image 的deb包得到如下目录:

​编辑

6. 重复编译 kernel

7. 如果对内核做了修改 可以使用下面的方法来更新开发板 linux 系统的内核和内核模块

编译之后

编译 linux 内核:

Linux操作系统框架

Linux内核的主要功能:

进程管理、内存管理、驱动、系统调用

Linux的内核目录结构:

结构图: 

详细介绍: 

a. arch/:这个目录包含了不同架构处理器的代码,如x86,arm,mips等。每个架构都有自己的子目录,如arch/x86/,arch/arm/等。在每个架构的子目录中,又有一些子目录和文件,如boot/,lib/,mm/,include/等,分别包含了特定平台的启动代码,库函数,内存管理,头文件

b. block/:这个目录包含了块设备的代码,如硬盘,光驱等。block/目录中主要包含了块设备的基本框架和I/O调度算法,以及一些通用的块设备驱动

c. crypto/:这个目录包含了加密算法的代码,如AES,SHA1,MD5等

d. drivers/:这个目录包含了设备驱动程序的代码,如键盘,鼠标,网卡,声卡,摄像头等。drivers/目录中的代码按照设备的类别进行分类,如char/,block/,input/,i2c/,spi/,pci/,usb/等

e. fs/:这个目录包含了文件系统的代码,如ext4,fat,ntfs,nfs,cifs等。fs/目录中的代码按照文件系统的类型进行分类,如ext4/,fat/,ntfs/等。在fs/目录中,还有一些通用的文件和子目录,如mount.h,dentry.c,proc/,sysfs/等,它们用于实现文件系统的基本功能和接口

f. include/:这个目录包含了内核所需的头文件,如linux/,asm/,uapi/等。头文件是用于声明变量,函数,结构,宏,常量等的文件,它们可以被其他的源文件引用,以便共享和重用代码。include/目录中的头文件按照不同的层次和用途进行分类,如linux/目录中的头文件是与平台无关的,asm/目录中的头文件是与平台相关的,uapi/目录中的头文件是用于内核和用户空间的API的

g. init/:这个目录包含了内核初始化的代码,如main.c,version.c,do_mounts.c等。init/目录中的代码是内核的入口和核心,它们负责调用其他子系统和模块的初始化函数

• ipc/:这个目录包含了进程间通信的代码,如sem.c,msg.c,shm.c等。进程间通信是指在不同的进程之间传递数据和信号的方法,它们可以让进程之间实现协作和同步。ipc/目录中的代码实现了一些常用的进程间通信机制,如信号量,消息队列,共享内存等

• kernel/:这个目录包含了内核的核心代码,如sched/,irq/,time/,fork.c,exit.c,signal.c等。kernel/目录中的代码实现了一些内核的基本功能和服务,如进程调度,中断处理,时间管理,进程创建,进程终止,信号处理等

• lib/:这个目录包含了内核需要引用的一些库函数的代码,如string.c,vsprintf.c,crc32.c等

• mm/:这个目录包含了内存管理的代码

• net/:这个目录包含了网络协议的代码,和网卡驱动不相关代码、

• scripts/:这个目录包含了内核编译所需的一些脚本,如Makefile,Kconfig,checkpatch.pl等

• tools/:这个目录包含了一些和内核交互的工具,如perf/,ftrace/,cpupower/,objtool/等。工具是用于分析和调试内核的程序,它们可以让内核的性能和稳定性更加优化和提高

---------------------------------------------------------------------

uname - a 补充

uname -a 是一个在 Linux 和 Unix 系统上常用的命令,用于显示当前系统的信息

具体来说,-a 选项(代表 "all")用于显示尽可能多的系统信息。

输出通常包含以下几个部分(但可能会因不同的系统和版本而异):

内核名称:例如 Linux

主机名:系统的主机名,这通常是你在 /etc/hostname 或使用 hostname 命令设置的名称。

内核版本号:当前运行的内核的版本。

内核发布日期:内核的发布或编译日期。

机器硬件名称:例如 x86_64 表示 64 位的 x86 架构。

处理器类型:例如 x86_64、i686 等。

操作系统:例如 GNU/Linux(但注意,这个信息并不总是显示)

例如,一个可能的输出是:

bash

Linux myhostname 5.4.0-7642-generic #38~1598903417~20.04~385a5d2-Ubuntu SMP PREEMPT Wed Sep 2 21:30:07 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

在这个例子中:

内核名称是 Linux

主机名是 myhostname

内核版本是 5.4.0-7642-generic

内核发布日期(或编译日期)是 Wed Sep 2 21:30:07 UTC 2020

机器硬件名称和处理器类型都是 x86_64

操作系统是 GNU/Linux

这个命令在需要快速查看系统信息、诊断问题或编写与特定系统相关的脚本时非常有用。

编译之前

注意这里的时间是UTC 时间

后续我们会通过这个命令验证内核编译是否成功

------------------------------------------------------

UTC 时间补充

UTC  时间和北京时间相差 8h

UTC(协调世界时,Coordinated Universal Time)是一种全球标准的时间标准,用于协调世界各地的时间。以下是关于UTC时间的详细介绍:

定义:UTC是根据原子钟生成的时间,被认为是“最精确的时间”。它的时间间隔被称为“秒”,并且具有高度的精确性和稳定性,不受地理位置的影响。

历史:UTC的概念在1960年由国际无线电咨询委员会规范统一,并在次年投入实际使用。它的计时基准是国际原子时(TAI),并通过加入闰秒来与世界时(UT1)保持同步。

应用:UTC在科学、政府、商业、金融等领域被广泛应用,如GPS导航、航天和通信。许多计算机和通信系统都以其为基准进行时间同步,以确保全球各地的时间一致性和协调性。

与GMT的关系:在1972年之前,格林威治时间(GMT)一直是世界时间的标准。然而,由于GMT是基于地球自转速度的观测和计算,其精度受到自然现象(如潮汐和季节变化)的影响。而UTC则基于原子钟的时间测量,具有更高的精度和稳定性。

特点:UTC以24小时制表示时间,并使用时区来调整不同地区的时间差异。它的特点是具有高度的精确性和稳定性,能够确保全球各地的时间准确性和一致性。

DTS  设备树补充:

DTS(Device Tree Source)设备树是一种用于描述硬件设备和资源的数据结构,它在嵌入式系统开发中扮演着重要的角色。以下是关于DTS设备树的详细介绍:

基本概念:DTS设备树采用树形结构来描述硬件设备的层次关系,每个节点代表一个硬件设备或子系统。节点可以包含设备的名称、类型、地址、中断号等信息,还可以包含子节点来表示该设备所连接的其他设备。

作用:通过DTS设备树,操作系统可以在运行时动态地识别和配置硬件,而无需在代码中硬编码驱动程序。这大大简化了硬件驱动的编写和管理工作,提高了系统的可移植性和可扩展性。

文件格式:DTS文件通常使用文本格式编写,易于阅读和编辑。文件名通常以.dts为扩展名,而.dtsi文件则用于描述SOC级信息(如CPU数量、主频、外设控制器信息等),可以被多个DTS文件共享以提高可重用性。

工作流程:在嵌入式系统开发中,DTS文件首先被编译成DTB(Device Tree Blob)二进制文件。这个编译过程通常使用设备树编译器(DTC)来完成。然后,在boot loader运行时,DTB文件被传递给操作系统。操作系统通过解析DTB文件来获取系统中所有硬件设备的配置信息,并据此进行初始化和配置。

应用:DTS设备树在嵌入式系统中的应用非常广泛,尤其是在嵌入式Linux系统中。通过DTS设备树,Linux内核可以自动识别并配置各种硬件设备,如CPU、内存、网卡、串口等。此外,DTS还支持热插拔功能,即在系统运行时动态添加或删除硬件设备,这对于需要频繁更换硬件设备的场景非常有用。

优点:DTS设备树将硬件信息从内核代码中分离出来,使得硬件信息更加清晰、易于管理和维护。同时,它也提高了系统的可移植性和可扩展性,使得开发人员可以更加容易地将代码移植到不同的硬件平台上。

总之,DTS设备树是一种非常重要的数据结构,它简化了硬件驱动的编写和管理工作,提高了系统的可移植性和可扩展性。在嵌入式系统开发中,DTS设备树发挥着不可替代的作用。

dtbs 可能是指Device Tree Blob Source的缩写,用于描述或存储设备树源文件的集合。Device Tree Blob(DTB)是设备树描述(Device Tree Description)的二进制表示,它描述了硬件的结构和配置,特别是在嵌入式系统中。

=====================================

Linux内核编译流程:

方法一:  官方内核编译:

//参考自官方的编译方式,详见(《OrangePi_Zero2_H616用户手册v4.0》 6.4 编译Linux内核)

1. 运行 build.sh 脚本, 记得加 sudo 权限

sudo ./build.sh

2. 选择 Kernel package, 然后回车 

3. 然后会提示是否需要显示内核配置界面

 如果不需要修改内核配置, 则选择第一个即可

 如果需要修改内核配置, 则选择第二个 

4. 接着选择开发板的型号 

因为我们使用的板子是 orangepi02 ,so我们选 orangepizero2

然后就进行编译了,注意这里编译耗时很长,我耗时一个半小时,可能其他条件因素,耗时几小时也是可能得。

编译完成

<h2 id="mySection">编译之前</h2>

5. 查看编译生成的内核相关的 deb 包 --  生成在这个 output/debs/  路径下

a. linux-dtb-next-sun50iw9_3.1.0_arm64.deb 包含有内核使用的 dtb 文件

b. linux-headers-next-sun50iw9_3.1.0_arm64.deb 包含内核头文件

c. linux-image-next-sun50iw9_3.0.1_arm64.deb 包含内核镜像和内核模块

如下图

我们需要的是镜像文件

解压  linux-image 的deb包得到如下目录:

其中 ./boot/下的:

config -- 是配置文件

vmlinuz 是我们需要的内核文件

6. 重复编译 kernel

 使用下面的命令无需通过图形界面选择, 可以直接开始编译kernel

sudo ./build.sh BOARD=orangepizero2 BRANCH=next BUILD_OPT=kernel KERNEL_CONFIGURE=no

7. 如果对内核做了修改 可以使用下面的方法来更新开发板 linux 系统的内核和内核模块

# 这里的ip 和用户名根据自身的修改

scp linux-image-next-sun50iw9_3.1.0_arm64.deb orangepi@192.168.1.11:/home/orangepi/

# 查看之前安装的内核:

dpkg -l | grep linux-image

# 卸载之前安装的内核

sudo apt purge -y linux-image-next-sun50iw9 # 也有可能是linux-image-next-sun50iw9

# 安装我们scp 过来的新内核, -i -->  install

sudo dpkg -i linux-image-next-sun50iw9_3.1.0_arm64.deb

# reboot  -- 重启,我们的内核才生效

编译之后

// 和之前  编译之前 的对比,发现我们的日期时间 已经修改为了今天的UTC,说明我们已经编译成功了

如果对dpkg不够了解的朋友请看这一篇:

一文带你了解 dpkg-CSDN博客

报错小插曲:

dpkg -i  下载的时候出现问题:dpkg-deb: error: paste subprocess was killed by signal

解决:

sudo dpkg -i --force-overwrite linux-image-next-sun50iw9_3.1.0_arm64.deb 

sudo apt-get -f install

可以尝试的方法:

我们这样解决,一次执行下面命令:

sudo apt-get clean

sudo apt-get update

sudo apt-get upgrade

sudo apt-get clean 是一个在Debian和Ubuntu等基于Debian的Linux发行版中常用的命令,它用于清理本地存储的已下载的.deb软件包文件。这些.deb文件通常在你使用apt-get命令安装、升级或删除软件包时被下载到/var/cache/apt/archives/目录中。

具体来说,sudo apt-get clean命令的作用如下:

清理下载的包:它删除/var/cache/apt/archives/目录下所有已下载的.deb软件包文件。这些文件在你成功安装软件包后通常是不再需要的,但它们会占用磁盘空间。

节省磁盘空间:如果你的系统经常进行软件包的安装、升级或删除操作,那么/var/cache/apt/archives/目录可能会积累大量的.deb文件,从而占用大量的磁盘空间。sudo apt-get clean命令可以帮助你释放这些空间。

不影响已安装的软件包:这个命令只会删除已下载的.deb文件,而不会影响已经安装在你的系统上的软件包。因此,你不需要担心运行这个命令会导致已安装的软件包被删除或损坏。

需要注意的是,虽然sudo apt-get clean命令可以释放磁盘空间,但如果你希望更深入地管理你的软件包缓存,你还可以考虑使用sudo apt-get autoclean命令。这个命令会删除过时的.deb文件(即那些在新版本的软件包管理器中不再需要的文件),而不仅仅是所有已下载的.deb文件。这样可以在保持一些可能在未来需要的.deb文件的同时,进一步节省磁盘空间。

---------------------------

=====================================================

 

方法二:

上述官方编译kernel的方法可以用以下步骤代替:

1. 清理旧配置文件及生成的文件

sudo apt-get install ccache #安装ccahe,用于编译加速

export PATH=$PATH:/home/mxjun/orangepi-build/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin #给root用户导入交叉编译环境,需要先切换到root用户

// 注意这里不能使用 whoami --> 我们需要切换到 root  用户操作 , 得到的用户名是root 

make ARCH=arm64 distclean

2. 配置内核, 更新内核依赖属性和新属性, 生成.config:

cp ../../external/config/kernel/linux-5.16-sun50iw9-current.config .config #拷贝默认配置

make ARCH=arm64 CROSS_COMPILE="aarch64-none-linux-gnu-" olddefconfig #这里执行make menuconfig 然后exit也是可以的

a. make olddefconfig 的作用是根据已有的 .config 文件生成一个新的 .config 文件,同时更新内核的依赖属性和新属性。它会使用旧的 .config 文件中的参数作为默认参数,不会询问用户的选择。它会将新添加的内核选项设置为默认值,也不会提醒用户。它会将旧的 .config 文件重命名为 .config.old 文件,以备后用.

b. make olddefconfig 的作用和 make oldconfig 类似,但是 make oldconfig 会以交互方式询问用户对

新配置的选择,而 make olddefconfig 不会

c. make menuconfig 是基于 Ncurses 图形界面去配置 .config 文件,它可以让用户在一个菜单式的界面

中选择和修改内核的各种选项,也可以查看选项的帮助信息,它是一种比较方便和直观的配置方式

3. 编译内核:

make -j6 ARCH=arm64 'CROSS_COMPILE=ccache aarch64-none-linux-gnu-' LOCALVERSION=-sun50iw9 Image modules dtbs

// 以ccache 高速缓存去加速交叉编译,    modules-->编译模块  dtbs -->编译设备树

4. 安装 内核 和 驱动:

make modules_install INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$PWD/_install ARCH=arm64 'CROSS_COMPILE=ccache aarch64-none-linux-gnu-' #安装驱动

make install INSTALL_PATH=$PWD/_install/boot #安装内核

//  参数: INSTALL_MOD_STRIP=1 --> 删除调试信息 or 链接调试符,节省编译空间,对orangepi不太明显,对×86 内核会明显

--------------------

或者直接打包成deb包:

cp external/patch/misc/headers-debian-byteshift.patch /tmp

make -j6 bindeb-pkg KDEB_PKGVERSION=3.1.0 KDEB_COMPRESS=xz BRANCH=next \

LOCALVERSION=-sun50iw9 KBUILD_DEBARCH=arm64 ARCH=arm64 DEBFULLNAME="Orange Pi" \

CROSS_COMPILE="ccache aarch64-none-linux-gnu-”

解读:

a.bindeb-pkg 是指定 make 命令使用 Debian 的格式来打包内核,生成一个 .deb 文件,这样可以方便

地在 Debian 系的系统中安装内核 。

b. KDEB_PKGVERSION=3.1.0 是指定打包的内核的版本号为 3.1.0,这个版本号可以自定义,也可以使用

内核的默认版本号 。

c. KDEB_COMPRESS=xz 是指定打包的内核使用 xz 的压缩格式,这样可以减少打包文件的大小,也可以

使用其他的压缩格式,如 gzip, bzip2 等 。

d. BRANCH=next 是指定编译的内核的分支为 next

c. LOCALVERSION=-sun50iw9 是指定编译的内核的本地版本为 -sun50iw9

d. KBUILD_DEBARCH=arm64 是指定打包的内核的架构为 arm64,这个架构是用来表示 64 位的 ARM

处理器。

e. ARCH=arm64 是指定编译的内核的架构为 arm64 。

f. DEBFULLNAME=Orange Pi 是指定打包的姓名为 Orange Pi。

======================================================

 Linux根文件系统

根文件系统也叫roofs,Linux 根文件系统是指整个文件系统的最顶层,以 "/" 来表示。它是内核启动时所挂载的第一个文件系统,包含了系统运行所必需的目录和文件:

1. /bin目录下存放着系统需要的可执行文件比如ls、mv、cp等命令,现在新根文件系统的像ubuntu等

debian系的rootfs, 基本都是软链接到/usr/bin目录下

2. /dev目录下面存放着的文件都与设备有关,此目录下的文件都是设备文件。

3. /etc目录存放Linux下所必须的库文件

4. /mnt目录, 临时挂载目录,可以在从目录下创建空的子目录

5. /proc、sys 目录, Linux虚拟文件系统,由内核生成各类节点

6. /sbin 一般软链到/usr/sbin下,一般存放一些root权限才能执行的命令

7. /lib 软链接到/usr/lib目录,用于存放库文件

8. /usr/ 存放lib bin sbin目录, 另外的share目录里面存放的是共享、只读的程序和数据

9. /tmp/存放临时文件或目录

10. /root目录 系统管理员(root)的主文件夹,即是根用户的目录,与此对应,普通用户的目录

是/home下的某个子目录。

11. /var目录、与/usr目录相反,/var目录中存放可变的数据,比如log文件\临时文件等。

12. /home目录,系统默认的用户文件夹,它是可选的,对于每个普通用户,在/home目录下都有一个以用户名命名的子目录,里面存放用户相关的配置文件。

根文件系统的编译详见(《OrangePi_Zero2_H616用户手册v4.0》 6.5. 编译 rootfs )

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。