在MacOS上为树莓派交叉编译Linux Kernel
因为在Pi的性能有限,在上面build kernel特别慢,所以需要使用性能强一点的机器进行交叉编译。
我在MacOS上,使用Docker的archlinux虚拟机进行编译。这篇文章简单记录在MacOS上为树莓派交叉编译内核的过程。
关于交叉编译Pi的Linux Kernel,可以参考树莓派相关文档1。重点是看文档里的Cross-compiling
部分。具体的内核编译部分不是本文重点,就不做过多的介绍了。
关于交叉编译,需要一个Linux的编译环境。为此,我已经准备好了相关的build image,可以从docker hub上直接取得:
$ docker pull weli/archlinux
这个image拿到以后,在创建容器之前,我们还要在Pi和MacOS两边各做一些配置工作。
要达成的目标是:在docker的容器里面交叉编译好内核,然后通过make module_install
命令,直接把内核配套的moduels安装到Pi的Linux系统当中的指定位置(Kernel build除了会生成新的kernel image,还会生成新的module tree文件和module文件,这些文件需要通过make安装到操作系统的指定位置)。
为了实现上面的目标,就需要在容器里面能够挂装Pi这边的操作系统根分区。因为容器是运行在MacOS上面的,因此就要允许MacOS能够通过网络挂装Pi的操作系统根分区。这样,在MacOS里面再把Pi的挂装分区映射进容器里。
所以首先要做的是把Pi的分区挂装到MacOS上面。为了这个目标,我们要让Pi这边的操作系统允许root进行ssh登录。因此我先在MacOS的主机上登录pi的系统:
$ ssh weli@pi
我的pi上面安装的是Arch Linux操作系统,并且配置好了ssh服务,所以像上面这样登录即可。登录后如下所示:
然后编辑sudoers
这个文件:
$ sudo vim /etc/ssh/sshd_config
打开文件以后,找到PermitRootLogin
的这行,配置为:
PermitRootLogin yes
效果如下:
编辑完成后,重启一下sshd
服务:
$ sudo systemctl restart sshd
然后确认sshd服务正常工作了:
接下来我们要从MacOS这边通过sshfs登录Pi的root账号,并挂装Pi的系统根分区。为了这个目标,我们要在MacOS上面安装osxfuse和sshfs。这两个项目的地址在一起:
https://osxfuse.github.io/
从这个网站下载并安装好osxfuse和sshfs,这两个工具可以支持我们在MacOS上远程挂装Linux的分区。
安装好以后,我们就可以使用sshfs
命令来挂装Pi的远程分区。下面是命令:
$ sshfs root@pi:/ /mnt/arch
挂装后,可以使用df
命令看看硬盘的挂装情况:
可以看到整个Pi的系统根分区已经挂装到MacOS的/mnt/arch
目录了。
此时我们可以创建container并启动:
$ docker run -i -t -v /mnt/arch:/mnt/arch weli/archlinux bash
注意上面的命令当中的-v
选项,我们把MacOS的/mnt/arch
映射到了container的系统当中的/mnt/arch
目录上。
此时我们已经登录进了容器,并且可以看到挂装好的远程Pi的分区:
此时,我们可以在这个容器里做kernel的交叉编译,并往安装拷贝Pi的分区里面安装拷贝内核了。
我在arch/linux
这个docker image里面已经配置并交叉编译好了一个内核,此时可以按照Pi的文档1执行安装命令试试看:
$ export PATH=$PATH:/home/weli/arm/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
$ KERNEL=kernel7
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/arch modules_install
执行完上面的命令,可以看到modules的安装过程:
这样,我们就又了一个很方便的交叉编译环境,并且编译后的kernel可以方便地导入Pi的系统当中。
最后,我们来比对一下交叉编译和在Pi上直接编译内核的性能差距。下面左边是在MacOS的Docker容器里做交叉编译,右边是在Pi的主机上进行直接编译:
可以看到性能差距明显。
References
- 上一篇 在树莓派上编译Linux内核
- 下一篇 为树莓派编译Kdump kernel