Ubuntu 20.04打RT实时内核补丁

编译实时内核并安装

查看当前内核版本

uname -r

笔者当前版本为 5.15.0-46-generic ,去下面网址中下载版本相近的内核文件和补丁文件,笔者选择的是 linux-5.15.113.tar.gz 和 patch-5.15.113-rt64.patch.gz ,可以先下 patch 包,然后根据对应的版本找内核包,不过不一定需要版本完全一致,相近的版本大概率也是可行的,如果需要某些工具如 linux-tools-5.15.0-113-generic,建议先用 apt 搜一搜是否支持对应版本

https://www.kernel.org/pub/linux/kernel/
https://www.kernel.org/pub/linux/kernel/projects/rt/

解压内核然后解压补丁,版本不同的话可以使用 TAB 键来补全

tar -xzvf linux-5.15.113.tar.gz
cd linux-5.15.113
gzip -cd ../patch-5.15.113-rt64.patch.gz | patch -p1 --verbose

安装依赖

sudo apt-get install autoconf bison build-essential dkms dwarves fakeroot flex libelf-dev libiberty-dev libidn11 libidn11-dev libncurses-dev libpci-dev libssl-dev libudev-dev minizip openssl zlibc zstd

复制当前内核的配置文件(用 TAB 补全),进入 config 交互界面调整下面设置,SAVE 后 EXIT

# 想重新生成 .config 可以使用 make defconfig

cp /boot/config-$(uname -r) .config
make menuconfig
General Setup -> Timers subsystem -> Timer tick handling 设置为 Full dynticks system
General Setup -> Timers subsystem 开启 High Resolution Timer Support
General Setup -> Preemption Model 设置为 Fully Preemptible Kernel(RT)
Processor type and features -> Timer frequency 设置为 1000 HZ

然后编辑 .config 并修改以下内容

sudo vim .config
CONFIG_SYSTEM_TRUSTED_KEY=""
CONFIG_SYSTEM_REVOCATION_KEYS="" 

apt 安装某些工具依赖内核版本号,因此可以修改一下 Makefile,改成 5.15.0-113-generic 的形式,如果打了实时内核补丁,后面会自动加上-rt后缀(目前还没找到解决方法)

VERSION = 5
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION = -113-generic

编译内核,线程数设为和 CPU 线程数相同

make -j`nproc` deb-pkg

安装内核,* 不要替换,所有编译后的文件都需要安装

sudo dpkg -i ../*.deb

 

图形化界面更换内核

如果没有成功设置为新内核,可以尝试用图形界面设置一下

sudo add-apt-repository ppa:danielrichter2007/grub-customizer
sudo apt-get update
sudo apt-get install grub-customizer
grub-customizer

保存后重启系统 

sudo reboot -f

 

命令行更换内核

当然也可以用命令行更换内核,查看当前所有已安装内核

grep "menuentry '" /boot/grub/grub.cfg

(如果是用 dpkg 方式安装的一般不需要这一步)找到新安装的内核并设置为默认启动项

sudo grub-set-default 'Ubuntu, Linux 5.15.0-113-generic'

可以设置开机等待时间手动选择内核,默认以新内核启动,高级选项里面可以看到旧内核

sudo vim /etc/default/grub
# 修改下面键值
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=5

更新grub后重启

sudo update-grub
sudo reboot -f

 

重启后查看内核是否更新

uname -r

可以自动删除多余的内核

sudo apt autoremove --purge

也可以手动卸载不需要的内核

dpkg --list | grep linux-image
sudo apt-get purge linux-image-xxx

 

安装 Nvidia 显卡驱动

首先重启切回非实时内核,然后禁用nouveau,在文件末尾插入以下内容

sudo gedit /etc/modprobe.d/blacklist.conf
blacklist nouveau
options nouveau modeset=0

保存后重启生效

sudo update-initramfs -u
reboot

重启后验证,如无任何输出则生效

lsmod | grep nouveau

卸载显卡驱动

sudo apt purge nvidia*

去 Nvidia 官网下载安装文件后安装(即不能直接安装二进制版本),在有 DKMS 字样的页面选择 YES ,其他都选择 NO ,否则可能无法开机,因此先设定好 root 密码再重启

chmod +x xxx.run
sudo bash ./xxx.run

如果不慎选错无法开机,则重启进 Recovery Mode 后卸载驱动,重启后若提示 nvidia-drm 相关错误无法安装则输入第二段内容

mount -n -o remount,rw /
apt purge nvidia*
rm /etc/X11/xorg.conf
reboot
systemctl isolate multi-user.target
# 进root账户
modprobe -r nvidia-drm
systemctl start graphical.target

查看是否安装成功

nvidia-smi

重启切回实时内核,然后保存下面内容为 install-nvidia.sh记得修改第四行的文件名

原始版本(运行时下载)
https://github.com/ApolloAuto/apollo-kernel/blob/master/linux/install-nvidia.sh

查看代码

#!/bin/bash

BUILD_BASE=`pwd`
NV_FILE="NVIDIA-Linux-x86_64-xxx.run"  # 这里改成自己下载的.run文件名(之前安装过的)
#NV_URL="https://us.download.nvidia.cn/XFree86/Linux-x86_64/430.50/${NV_FILE}"  # 之前已经下好了显卡驱动.run文件,就不用从网上下载了,直接注释掉,而且如果要下载的话,则慢
NEED_TO_COMPILE_NV_KO=1

function clean_env() {

    [ -d ./${NV_DIR} ] && rm -rf ./${NV_DIR}
}

function check_env() {
    
    # check if in rt kernel
    uname -r | grep rt 1>/dev/null 2>&1 
    if [ $? -ne 0 ]
    then
        echo "Not in rt kernel, Please install apollo kernel and reboot machine first."
        exit 2
    fi

    # check if nv ko already in kernel
    if [ ! -f /lib/modules/`uname -r`/kernel/drivers/video/nvidia.ko ]
    then
        export NEED_TO_COMPILE_NV_KO=1
    fi
}

function prepare_nv() {

    ## download nv install file from nvidia home page 
    #if [ ! -f ./${NV_FILE} ]
    #then
    #   echo "Downloading ${NV_FILE} from nvidia website..."
    #    wget ${NV_URL} -O ${NV_FILE}
    #    if [ $? -ne 0 ]
    #    then
    #        echo "Downloading ${NV_FILE} failed, please check your network connection!"
    #        rm -rf ./${NV_FILE}
    #        exit 1
    #    fi
    #fi
    ###########上面是下载驱动的代码,我们已经提前下载好了,就不需要这段代码了,直接注释掉############

    # +x 
    chmod +x ./${NV_FILE}
    echo "Extracting nvidia install run file..."
    ./${NV_FILE} -x 1>/dev/null 2>&1
    NV_DIR="`echo ${NV_FILE} | awk -F '.run' '{print $1}'`"
    NV_VERSION="`echo ${NV_FILE} | awk -F '-' '{print $4}' | awk -F '.run' '{print $1}'`"

    export NV_DIR
    export NV_VERSION
    export NVIDIA_SOURCE="${NV_DIR}/kernel"
}

function install_lib() {
   
    NV_LIB_OUTPUT_PATH="/usr/lib/x86_64-linux-gnu/"
    NV_BIN_OUTPUT_PATH="/usr/bin/"

    [ -f ./${NV_DIR}/libnvidia-ml.so.${NV_VERSION} ] && /bin/cp -f ./${NV_DIR}/libnvidia-ml.so.${NV_VERSION} ${NV_LIB_OUTPUT_PATH}
    [ -f ./${NV_DIR}/libnvidia-fatbinaryloader.so.${NV_VERSION} ] && /bin/cp -f ./${NV_DIR}/libnvidia-fatbinaryloader.so.${NV_VERSION} ${NV_LIB_OUTPUT_PATH}
    [ -f ./${NV_DIR}/libnvidia-ptxjitcompiler.so.${NV_VERSION} ] && /bin/cp -f ./${NV_DIR}/libnvidia-ptxjitcompiler.so.${NV_VERSION} ${NV_LIB_OUTPUT_PATH}
    [ -f ./${NV_DIR}/libcuda.so.${NV_VERSION} ] && /bin/cp -f ./${NV_DIR}/libcuda.so.${NV_VERSION} ${NV_LIB_OUTPUT_PATH}
    [ -f ./${NV_DIR}/nvidia-modprobe ] && /bin/cp -f ./${NV_DIR}/nvidia-modprobe ${NV_BIN_OUTPUT_PATH}
    [ -f ./${NV_DIR}/nvidia-smi ] && /bin/cp -f ./${NV_DIR}/nvidia-smi ${NV_BIN_OUTPUT_PATH}

    chmod +x /usr/bin/nvidia*
    chmod +s /usr/bin/nvidia-modprobe

    # link for nvidia
    /bin/rm -rf /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1  /usr/lib/x86_64-linux-gnu/libnvidia-ml.so
    /bin/ln -s /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.${NV_VERSION} /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
    /bin/ln -s /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 /usr/lib/x86_64-linux-gnu/libnvidia-ml.so

    /bin/rm -rf /usr/lib/x86_64-linux-gnu/libcuda.so  /usr/lib/x86_64-linux-gnu/libcuda.so.1
    /bin/ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.${NV_VERSION} /usr/lib/x86_64-linux-gnu/libcuda.so.1
    /bin/ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.1 /usr/lib/x86_64-linux-gnu/libcuda.so

    # take effect
    /sbin/ldconfig 1>/dev/null 2>&1
}

function build_nv() {

    if [ ${NEED_TO_COMPILE_NV_KO} == 0 ]
    then
        return
    fi

    NVIDIA_MOD_REL_PATH='kernel/drivers/video'
    NVIDIA_OUTPUT_PATH="/lib/modules/`uname -r`/${NVIDIA_MOD_REL_PATH}"
    CPUNUM=`cat /proc/cpuinfo | grep processor | wc | awk -F " " '{print $1}'`

    export IGNORE_PREEMPT_RT_PRESENCE=true
    cd ${NVIDIA_SOURCE} && make -j ${CPUNUM} module
    cd ${BUILD_BASE}

    unset IGNORE_PREEMPT_RT_PRESENCE

    mkdir -p ${NVIDIA_OUTPUT_PATH}

    [ -f ${NVIDIA_SOURCE}/nvidia.ko ] && cp ${NVIDIA_SOURCE}/nvidia.ko ${NVIDIA_OUTPUT_PATH}
    [ -f ${NVIDIA_SOURCE}/nvidia-modeset.ko ] && cp ${NVIDIA_SOURCE}/nvidia-modeset.ko ${NVIDIA_OUTPUT_PATH}
    [ -f ${NVIDIA_SOURCE}/nvidia-drm.ko ] && cp ${NVIDIA_SOURCE}/nvidia-drm.ko ${NVIDIA_OUTPUT_PATH}
    [ -f ${NVIDIA_SOURCE}/nvidia-uvm.ko ] && cp ${NVIDIA_SOURCE}/nvidia-uvm.ko ${NVIDIA_OUTPUT_PATH}

    depmod -a
}

# check environment
check_env

# prepare for nvidia
prepare_nv

# build nvidia.ko
build_nv

# install user lib
install_lib

# clean environment
clean_env

echo "Done to install nvidia kernel driver and user libraries."

执行脚本

chmod +x ./install-nvidia.sh
sudo bash ./install-nvidia.sh

查看驱动信息

nvidia-smi

设置首选独显

sudo apt install nvidia-prime
sudo prime-select nvidia

测试实时性,观察最右侧的 MAX ,如果一直只有几十,说明是实时系统了,如果是非实时系统,运行一段时间会增加到几千甚至上万

sudo apt-get install rt-tests
sudo cyclictest -a -t -p 99

 

感谢

ubuntu打实时内核补丁教程以及安装后显卡驱动问题解决方法
https://blog.csdn.net/weixin_39275295/article/details/119173247

Ubuntu 20.04安装RT-PREEMPT实时内核补丁
https://blog.csdn.net/qq_28882933/article/details/118293544?spm=1001.2014.3001.5506

为ROS 2构建实时Linux
http://dev.ros2.fishros.com/doc/Tutorials/Building-Realtime-rt_preempt-kernel-for-ROS-2.html

使用实时补丁内核的ubuntu中安装nvidia显卡驱动
https://blog.csdn.net/tang05505622334/article/details/103477086

如何为 Apollo 安装低时延/实时内核
https://daobook.github.io/apollo/docs/howto/how_to_install_apollo_kernel_cn.html?highlight=realtime

How to unload kernel module 'nvidia-drm'?
https://unix.stackexchange.com/questions/440840/how-to-unload-kernel-module-nvidia-drm

How can I remove nvidia drivers?
https://askubuntu.com/questions/50617/how-can-i-remove-nvidia-drivers

jlelli/rt-tests
https://github.com/jlelli/rt-tests

 

posted @ 2022-09-15 02:37  Pyrokine  阅读(6011)  评论(0编辑  收藏  举报