本文包括:
1. 交叉编译树莓派ubuntu系统可使用的内核(debian package格式的可安装文件)
2. 使用WPA_Supplicant连接wifi
——————————————————————————————————————————
1.1 情景重现:
树莓派开机,运行
$ uname -r
结果显示是 5.15 版的内核。 因此去Github下载了 5.4 版的内核源文件,想试验一下更新(切换?)内核。跟着官方教程 <The Linux kernel > 一步步往下做,还算顺利。直到这一步:
$ sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img $ sudo cp arch/arm64/boot/Image mnt/fat32/$KERNEL.img
mnt/fat32 路径下运行下:
$ ls -l -h | grep img
找出的像内核的玩意,也只有initrd.img 了。把它备份,然后将编译好的Image复制到 mnt/fat32/ 下,改名为kernel8.img(树莓派4B 64位内核的默认名字)。接下来照猫画虎,一步步完成。接着插卡,开机,就启动不了了。屏幕卡在 "Initramfs unpacking faild: invalid magic at start of compressed archive"。然后我在百度、谷歌、搜狗搜索了两天,了解了内核发展史上,使用过的各种压缩解压算法,比如lz4,gzip等等等。也尝试着在各种配置文件里,修改内核启动时的解压算法选项。啥用都没有。之后又郁闷了一个周日,为啥initrd.img 28M,我编译的内核才十几M?直到我灵光一闪,去搜索了initrd.img。原来这位根本就不是内核啊。可是 mnt/fat32/ 下,除了这位,找不到第二个像内核的啦。:-(
后来我才知道,原来ubuntu跟树莓派官方系统的内核文件结构是不同的。刷回树莓派系统,迫不及待的打开 mnt/fat32/ 查看,果然有kernel8.img。
但是如果就是想将ubunut 5.15版的内核改成5.4版,该怎么办?方法总结如下。
1.2. 编译树莓派ubuntu系统可使用的内核(debian package格式的可安装文件)
参考网页:編譯 Raspberry Pi 4 的 Kernel Image (十分感谢这篇博客,因为基本上没找到其它有用的资料。其它为数不多涉及到该主题的内容,也大多是些论坛内零零散散的回答。)
#1 准备编译环境 $ sudo apt update # 创建编译linux所需要的环境 $ sudo apt build-dep linux # 上边那步做的还不够,还需要安装这些软件 $ sudo apt install build-essential libncurses-dev linux-tools-common fakeroot # man apt-get 对build-dep的解释 # build-dep # build-dep causes apt-get to install/remove packages in an attempt # to satisfy the build dependencies for a source package. By default # the dependencies are satisfied to build the package natively. If # desired a host-architecture can be specified with the # --host-architecture option instead. #2. 安装交叉编译器 $ sudo apt install crossbuild-essential-arm64 #3. 下载内核源文件 #一般下载ubuntu官方组织提供的版本。虽然原博客提供了直接编译mainline内核的方法,但麻烦很多。 #所谓mainline版本就是在 kernel.org 发布的版本。 $ mkdir ~/kbuild $ cd ~/kbuild $ git clone --depth=1 git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux-raspi/+git/focal #4. 交叉编译 # 所需环境变量 $ export CC=aarch64-linux-gnu-gcc $ export $(dpkg-architecture -aarm64) $ export CROSS_COMPILE=aarch64-linux-gnu- $ fakeroot debian/rules clean $ fakeroot debian/rules binary-headers binary binary-perarch # fakeroot 和 debian/rules 的简单解释 # fakeroot: # Gives a fake root environment, to remove the need to become root for a package build. #debian/rules: # The debian/rules script is the executable script to build the Debian package. #5. 安装内核 #生成的几个.deb在顶层目录,即~/kbuild下 #将它们复制到树莓派 /home/username 下,安装即可
$ sudo dpkg -i *.deb $ ync; sudo reboot
亲测可用。但是对于这种debian/rules的编译方法,如何编译外部模块(比如驱动),我试验了好久都没有解决。因为用make编译外部模块时,会提示缺少配置文件(比如.config)。这些配置文件是直接通过make编译内核时,一定会有先配置好的。而用 debian/rules编译内核时,跳过了配置这一步(用了debian/rules的配置方法,当然其配置文件也存放在某个目录下,但不在源码根目录下)。因此,直接用make编译外部模块时,会找不到配置文件。而如何用debian/rules的方式编译外部模块,又找不到太多的相关资料,只知道个m-a(module-assistant,https://wiki.debian.org/ModuleAssistant)命令。虽然用ubuntu源代码build目录下的某个目录,替换源代码目录,可解决找不到配置文件的问题。但又会有其它问题。总之,现在还不会。
而换回树莓派官方系统后,很容易就配置成功了。因为树莓派一开始就是直接用make直接编译的。比如:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
而编译前,它显示的配置了内核:
cd linux KERNEL=kernel8 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
——————————————————————————————————————————
2.1 情景重现:
树莓派官方系统,用systemctl设置开机自动连接wifi后,会出现启动死循环。即启动失败,掉电,又加电,又启动失败。如此循环,一直不知道为啥。后来在树莓派的ubuntu系统上,测试systemctl start testwifi.service时(blog1里有介绍),一start就关机。一enable就进入启动死循环。当我把服务所执行的脚本 test.sh 的命令减少到只有一条 nmcli dev wifi connect "myssid" password "mypassword" 时,情况还是如此。我就知道nmcli靠不住了。
2.2 WPA_Supplicant连接wpa2网络
参考网页:Using WPA_Supplicant to Connect to WPA2 Wi-fi from Terminal on Ubuntu 16.04 Server
#1 确保无线网卡可用(一般可以跳过) # 因为各国家/地方的法律问题等,无线网卡的初始状态可能是被锁定 $ sudo apt install rfkill # 检查无线网卡状态 $ rfkill list # 如果无线网卡被锁住,解锁 $ rfkill unblock wifi #2 如果系统有NetworkManager服务,关闭它 # 可先查看下,当前系统有无此服务 $ sudo systemctl status NetworkManager # 有则关闭 $ sudo systemctl stop NetworkManager $ sudo systemctl disable NetworkManager #3 查看无线网卡 # 一般叫wlan0,此时ACCESS POINT状态为 not associated $ iwconfig # 打开网卡 $ sudo ifconfig wlan0 up # 搜一下,要连接的wifi能不能搜到 sudo iwlist wlan0 scan | grep your-ESSID #4 使用wpa_supplicant连接网络 # 生成配置文件,同时文件里的密码会被加密 $ wpa_passphrase your-ESSID your-passphrase | sudo tee /etc/wpa_supplicant.conf # 连接wifi,这个-B是指在后台运行,所以一次iwconfig查不到连接状态,可以在稍等一会。 sudo wpa_supplicant -B -c /etc/wpa_supplicant.conf -i wlan0 #查看无线网卡,此时ACCESS POINT状态为所连接的wifi iwconfig #此时还没有分配ip $ sudo dhclient wlan0 #查看无线网卡,此时应该有ip了,且可以上网了。ping baidu.com能通 iwconfig #发布ip #-r #Tell dhclient to release the current lease it has from the server. This #is not required by the DHCP protocol, but some ISPs require their #clients to notify the server if they wish to release an assigned IP address. $ sudo dhclient wlan0 -r