在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

  1. https://www.raspberrypi.org/documentation/linux/kernel/building.md  2