• 在Ubuntu上编译安装linux内核详细过程


    Ubuntu上编译安装linux内核详细过程

    时间:20220414,版本:V0.1

    作者:robotech_erx

    1.预备

    1.1解释题目

    一个linux系统需要3个组件:内核、根文件系统、bootloader。不管是哪个发行版或者嵌入式系统,内核都是一样的。Bootloader也相对简单,pc上用grub,嵌入式系统上用uboot。比较麻烦的是构建根文件系统(init系统,GUI,编译工具,shell,各种工具等等)。嵌入式系统上还好说,有很多的工具可以快速的搞出一个最小(或者不那么小的)根文件系统。PC上的根文件系统,工作量就很庞大了,不是那么快能完成的。其实一个发行版,比如ubuntu,叫做linux根文件系统更准确。

    因此,这里仅仅是编译一个新的内核并安装,修改一下grub,让他加载新的内核启动系统。根文件系统还是Ubuntu原来的。

    1.2关于linux内核版本号和Ubuntu版本号

    查看当前linux内核版本

    $ uname -r

    5.13.0-39-generic

    含义如下:major#.minor#[.patchlevel][-EXTRAVERSION]

    对应到5.13.0-39-generic

    5:主版本号

    13:次版本号,一个次版本号出现通常代表着是一个稳定版本

    0patchlevelapplied on occasion to the stable kernel when significant bug/security fixes are required.

    -39-genericEXTRAVERSION,又称作localversion,通常是发行版使用,用于标记发行版对内核的修改。

    1.3发行版本和内核版本的对应关系

    从版本号可以知道(-39-generic),发行版的内核与原版相比是有修改的。下载发行版的代码可以参考:

    https://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide

    https://cloud.tencent.com/developer/article/1439068 找到运行的Ubuntu版本对应的内核源码

    我们这里使用原始版本的代码编译一个内核,但是文件系统使用的还是ubuntu20.04的。Ubuntu版本和内核版本是有关联的。例如ubuntu 20.04 里,apt-cache search linux-image查看。最旧的版本也是5.4。如果使用4.x的内核,可能会有一些问题(哪些问题呢?)。

    2.编译

    2.1下载内核、安装工具

    这里编译的版本是5.17.2。(原有版本是Linux version 5.13.0-39-generic)。

    安装需要的工具:

    $sudo apt update

    $sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison dwarves

    上面的工具编译4.x的内核足够了,但是5.13之后的还需要一些别的工具

    sudo apt install zstd #5.13之后支持zstd压缩

    2.2获取起始的.config文件

    完全手工指定内核的配置选项不现实,一般都是找一个.config文件然后以这个文件为基础进行修改。这个起始的配置文件一般3种获取的方法:

    1)使用源码里自带的defconfig文件。如果是嵌入式系统,使用已有的defconfig配置是个不错的选择。

    2)可以使用Ubuntu20.04自己的config文件作为配置的基础。

    在源码文件根目录下:

    $ cp /boot/config-$(uname -r) ./.config

    直接复制问题是,一些新内核新增加的配置需要自己手工配置了。

    3)使用localmodconfig 对象获取一个精简的编译配置。

    为了能够应对各种各样的环境,发布版的内核包含很多内核模块。但是在某个特定机器,例如,大家自己平时使用的PC上实际用到的模块只是其中的极小一部分。重新构建内核时,对不使用的模块进行编译就会浪费时间。

    localmodconfig作为make的目标,kbuild系统会获取一个当前在用的模块的列表,生成仅以正在使用的内核模块为对象的.config文件,从而大幅度减少编译时间。

    在源码文件根目录下:

    lsmod > /tmp/lsmod.now

    make LSMOD=/tmp/lsmod.now localmodconfig

    Localmodconfig也是使用/boot/config-$(uname -r) ./.config作为基准的。输入命令后,两个kbuild会询问对于新内核增加的那些配置的选择。

    这里使用的是第3种方法。

    2.3配置menuconfig

    $ make menuconfig

    这里主要是想编一个可GDB调试的内核,所以有以下两个配置:

    1)在生成的vmlinux中保留调试信息:

    Kernel hacking--->

    Compile-time checks and compiler options  --->

    [*] Compile the kernel with debug info  

    [*] Provide GDB scripts for kernel debugging   

    2)启用KGDB/KDB支持:

    Kernel hacking    --->

    Generic Kernel Debugging Instruments   --->                                                                         

    --- KGDB: kernel debugger                                    

    [*]   KGDB: use kprobe blocklist to prohibit unsafe breakpoints        

    <*>   KGDB: use kgdb over the serial console            

    [ ]   KGDB: internal test suite                        

    [*]   KGDB: Allow debugging with traps in notifiers    

    [*]   KGDB_KDB: include kdb frontend for kgdb                         

    (0x1)   KDB: Select kdb command functions to be enabled by default    

    [*]     KGDB_KDB: keyboard as input device                         

    (0)     KDB: continue after catastrophic errors                       

    不同的内核版本中,具体的位置可能不太一样。

    不论是第2还是第3种方法设置的初始配置文件,上述2个配置都是默认选中的。所以这里仅仅是查看一下~

    2.4编译

    make -j4            #使用4线程编译

    遇到一个出错:

    make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'.  Stop.

    查了一下,需要关闭两个配置

    第一个是

    CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"

    找到他修改成:

    CONFIG_SYSTEM_TRUSTED_KEYS=""

    或者运行脚本关闭:

    scripts/config --disable SYSTEM_TRUSTED_KEYS

    or

    scripts/config --set-str SYSTEM_TRUSTED_KEYS ""

    第二个是

    CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"

    关闭:

    scripts/config --disable SYSTEM_REVOCATION_KEYS

    具体原理没有深究。参考自:

    (https://askubuntu.com/questions/1329538/compiling-the-kernel-5-11-11)

    编译完成后,显示

    ...

    Kernel: arch/x86/boot/bzImage is ready  (#2)

    括号里的 #2意思是这个内核的第二次构建。

    除了bzImage 其他生成的东西系包括:

    vmlinux,比较大的文件(900MbzImage 不到10M

    modules,以模块方式编译的驱动们。执行如下命令查看都生成了哪些模块:

    $ find . -name *.ko

    2.5安装内核、模块和Initramfs

    两个make命令完成这个工作。

    安装模块

    $sudo make modules_install  #安装模块

    “安装”就是把模块文件拷贝到根文件系统的目录中,这里是/lib/modules/$(uname -r)/

    需要注意的是:

    ls -l /lib/modules/5.17.2/

    total 384

    lrwxrwxrwx  1 root root    34 4月  13 20:18 build -> /home/sunlion/Desktop/linux-5.17.2

    drwxr-xr-x 10 root root  4096 4月  13 20:18 kernel

    -rw-r--r--  1 root root 29941 4月  14 08:51 modules.alias

    -rw-r--r--  1 root root 27556 4月  14 08:51 modules.alias.bin

    -rw-r--r--  1 root root 10361 4月  13 20:18 modules.builtin

    -rw-r--r--  1 root root 26092 4月  14 08:51 modules.builtin.alias.bin

    -rw-r--r--  1 root root 12959 4月  14 08:51 modules.builtin.bin

    -rw-r--r--  1 root root 81270 4月  13 20:18 modules.builtin.modinfo

    -rw-r--r--  1 root root  7568 4月  14 08:51 modules.dep

    -rw-r--r--  1 root root 11475 4月  14 08:51 modules.dep.bin

    -rw-r--r--  1 root root   126 4月  14 08:51 modules.devname

    -rw-r--r--  1 root root  2983 4月  13 20:18 modules.order

    -rw-r--r--  1 root root    85 4月  14 08:51 modules.softdep

    -rw-r--r--  1 root root 71730 4月  14 08:51 modules.symbols

    -rw-r--r--  1 root root 81094 4月  14 08:51 modules.symbols.bin

    lrwxrwxrwx  1 root root    34 4月  13 20:18 source -> /home/sunlion/Desktop/linux-5.17.2

    符号连接buildsource 指向的是源码文件的安装目录,后面编写驱动需要提供给makefile,而且需要是编译配置过之后的源码,“纯”代码,.config文件都没有,是不行的。所以用于编译的源码放在一个合适的位置比较重要(例如 /usr/src/),这里放在桌面就比较随意了。最好是专门做一个环境变量来标志源码目录。

    安装内核

    $sudo make install          #安装内核

    执行后,输出如下:

    arch/x86/Makefile:154: CONFIG_X86_X32 enabled but no binutils support

    sh ./arch/x86/boot/install.sh 5.17.2 \

    arch/x86/boot/bzImage System.map "/boot"

    run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 5.17.2 /boot/vmlinuz-5.17.2

    run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.17.2 /boot/vmlinuz-5.17.2

    update-initramfs: Generating /boot/initrd.img-5.17.2

    run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.17.2 /boot/vmlinuz-5.17.2

    run-parts: executing /etc/kernel/postinst.d/update-notifier 5.17.2 /boot/vmlinuz-5.17.2

    run-parts: executing /etc/kernel/postinst.d/vboxadd 5.17.2 /boot/vmlinuz-5.17.2

    VirtualBox Guest Additions: Building the modules for kernel 5.17.2.

     

    VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what

    went wrong

    run-parts: executing /etc/kernel/postinst.d/xx-update-initrd-links 5.17.2 /boot/vmlinuz-5.17.2

    I: /boot/initrd.img.old is now a symlink to initrd.img-5.13.0-39-generic

    I: /boot/initrd.img is now a symlink to initrd.img-5.17.2

    run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.17.2 /boot/vmlinuz-5.17.2

    Sourcing file `/etc/default/grub'

    Sourcing file `/etc/default/grub.d/init-select.cfg'

    Generating grub configuration file ...

    Found linux image: /boot/vmlinuz-5.17.2

    Found initrd image: /boot/initrd.img-5.17.2

    Found linux image: /boot/vmlinuz-5.13.0-39-generic

    Found initrd image: /boot/initrd.img-5.13.0-39-generic

    Found linux image: /boot/vmlinuz-5.11.0-27-generic

    Found initrd image: /boot/initrd.img-5.11.0-27-generic

    Found memtest86+ image: /boot/memtest86+.elf

    Found memtest86+ image: /boot/memtest86+.bin

    done

    这段输出说明了make install完成的工作:

    1.复制bzImage System.map文件到 "/boot"目录;

    2.生成initramfs文件到/boot/initrd.img-5.17.2;

    3.更改grub的配置文件,把新内核的相关信息添加到配置中。

    重启,自动使用最新的内核,uname -a 可查看内核信息。(启动时,按住shift可进入grub的选择菜单,选择一个内核)

    2.6总结

    $ sudo apt update

    $ sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison dwarves zstd

    $ make distclean

    $ lsmod > /tmp/lsmod.now

    $ make LSMOD=/tmp/lsmod.now localmodconfig

    $ scripts/config --disable SYSTEM_TRUSTED_KEYS

    $ scripts/config --disable SYSTEM_REVOCATION_KEYS

    $ make menuconfig

    $ make -j4            #使用4线程编译

    $ sudo make modules_install  #安装模块

    $ sudo make install          #安装内核

      

    其他一些可能有用的menuconfig配置

    Kernel .config support:将.config配置信息保存在内核中,选上它及它的子项使得其它用户能从为文件/proc/config.gz 中得到内核的配置。

    参考:

    https://blog.csdn.net/u013014440/article/details/44154947

    Linux内核程序开发

  • 相关阅读:
    pythonldap 简单试用
    shell 将文件名读入数组
    pytest命令行传入自定义的参数到测试文件中
    Python实现在不同Linux主机之间拷贝文件
    使用minio搭建私有化对象存储服务
    CPU/GPU/NPU
    pytest 内置和自定义marker
    安装SQLite3引发的库问题
    C标准库——程序员等级
    这样还弄不死指针?
  • 原文地址:https://www.cnblogs.com/robotech/p/16152269.html
Copyright © 2020-2023  润新知