本文章是LLVM编译Linux系统的第二篇文章,介绍如何使用LLVM/Clang/musl工具链编译一个可以启动的Linux内核.

编译GNU assembler

大多数情况下LLVM提供的binutils已经兼容GNU binutils了,但是少数情况下, LLVM/Clang的内置汇编器的行为与GNU汇编器并不相同, 如果遇到编译Linux内核时Clang内置汇编器报错的情况,则需要使用GNU汇编器. ClangBuiltLinux项目为Clang编译Linux内核做出了大量的努力, 如果遇到此类错误, 可以去ClangBuiltLinux项目的issue区查看问题是否已知.

cd $DISTDIR && wget -qO- https://mirrors.tuna.tsinghua.edu.cn/gnu/binutils/binutils-2.37.tar.xz | tar xvJ && cd binutils-2.37
unset CFLAGS CXXFLAGS LDFLAGS #这部分是为Host编译的
export acx_cv_cc_gcc_supports_ada=no # 如果你的gcc/cc是clang的链接则需要此环境变量
./configure --prefix= --target=$TARGET --disable-nls --disable-werror --disable-ld --disable-gold --disable-gprof --disable-binutils
make -j13
DESTDIR=$HOME/.local/ make install

编译Linux内核

打开设置菜单

export ARCH=arm64 # 对应内核arch目录的子目录名/
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 menuconfig

请自行根据硬件调整配置,可以参考Gentoo的文档

总的来说,可以通过启动livecd来判断所需要的内核组件.对于计算机启动时就会加载的模块,选择[Y],对于USB设备则可以选择为[M],其他用不到的选择为[N].

对于x86_64 UEFI启动的计算机,建议编译时打开CONFIG_EFI_STUB选项,这样就可以直接从UEFI shell启动了.

对于树梅派3/4等arm设备,树莓派的fork的内核源码提供预先编写的配置.

make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 bcmrpi3_defconfig # Pi 2 (1.2+), Pi 3, Pi 3+, or Compute Module 3
make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 bcm2711_defconfig # Pi 4b+

如果只是想在虚拟机中测试的话,可以选择:

make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 tinyconfig
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 kvm_guest.config
# 启用 General setup --> Configure standard kernel features (expert users) --> Multiple users, groups and capabilities support
# 和 Enable support for printk
# 启用 Device Drivers --> Character devices --> Serial drivers --> ARM AMBA PL011 serial port support 
# 和 Support for console on AMBA serial port ( 如果你使用arm架构 )
# 启用 Kernel hacking --> printk and dmesg options --> Show timing information on printks
# 启用 File systems --> Pseudo filesystems --> /proc file system support
# 启用 File systems --> Pseudo filesystems --> sysfs file system support
# 启用 Executable file firmats --> Kernel support for scripts starting with #!
# 启用 Device Drivers --> Generic Driver Options --> Maintain a devtmpfs filesystem to mount at /dev

然后编译内核.

make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 -j13

对于x86系统会有以下输出

  BUILD   arch/x86/boot/bzImage
Setup is 15916 bytes (padded to 16384 bytes).
System is 19892 kB
CRC 17bccae5
Kernel: arch/x86/boot/bzImage is ready  (#1)

可以在arch/x86/boot/bzImage找到编译好的内核.可以用UEFI shell或者grub引导器启动这个内核.

对于arm64系统会有以下输出

  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm64/boot/Image
  GZIP    arch/arm64/boot/Image.gz

Image为内核文件,Image.gz为gzip压缩的内核,修改uboot或者其他引导器的配置文件可以启动这个内核, 也可以直接用qemu启动:

> qemu-system-aarch64 -m 64M -M virt -cpu cortex-a53 -kernel arch/arm64/boot/Image -nographic -append "console=ttyAMA0"
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.15.1-zen+ (han@musl) (clang version 13.0.0, LLD 13.0.0) #110 ZEN SMP Tue Nov 9 17:40:11 CST 2021
[    0.000000] Machine model: linux,dummy-virt
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv0.2 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 16 pages/cpu s33688 r0 d31848 u65536
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: kernel page table isolation disabled by kernel configuration
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16160
[    0.000000] Kernel command line: console=ttyAMA0
[    0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.000000] Memory: 57516K/65536K available (3072K kernel code, 610K rwdata, 340K rodata, 320K init, 255K bss, 8020K reserved, 0K cma-reserved)
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=1.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] Root IRQ handler: 0xffffffc010145db4
[    0.000000] GICv2m: range[mem 0x08020000-0x08020fff], SPI[80:143]
[    0.000000] arch_timer: cp15 timer(s) running at 62.50MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
[    0.000050] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns
[    0.001878] Console: colour dummy device 80x25
[    0.002848] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=250000)
[    0.002995] pid_max: default: 4096 minimum: 301
[    0.005089] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.005122] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.019348] rcu: Hierarchical SRCU implementation.
[    0.021194] smp: Bringing up secondary CPUs ...
[    0.021303] smp: Brought up 1 node, 1 CPU
[    0.021331] SMP: Total of 1 processors activated.
[    0.021372] CPU features: detected: 32-bit EL0 Support
[    0.021431] CPU features: detected: CRC32 instructions
[    0.022349] CPU: All CPU(s) started at EL1
[    0.022470] alternatives: patching kernel code
[    0.027233] random: get_random_bytes called from 0xffffffc01038a914 with crng_init=0
[    0.028666] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.030098] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.032806] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.035296] ASID allocator initialised with 65536 entries
[    0.035330] Serial: AMBA PL011 UART driver
[    0.049279] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 47, base_baud = 0) is a PL011 rev1
[    0.057230] printk: console [ttyAMA0] enabled
[    0.061698] vgaarb: loaded
[    0.069121] clocksource: Switched to clocksource arch_sys_counter
[    0.072978] NET: Registered PF_INET protocol family
[    0.074091] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.075695] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
[    0.075954] TCP established hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.076237] TCP bind hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.076530] TCP: Hash tables configured (established 512 bind 512)
[    0.077986] UDP hash table entries: 128 (order: 0, 4096 bytes, linear)
[    0.078397] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes, linear)
[    0.079387] PCI: CLS 0 bytes, default 64
[    0.083992] workingset: timestamp_bits=62 max_order=14 bucket_order=0
[    0.084285] 9p: Installing v9fs 9p2000 file system support
[    0.084853] io scheduler mq-deadline registered
[    0.085207] io scheduler kyber registered
[    0.098168] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    0.100453] NET: Registered PF_INET6 protocol family
[    0.105579] Segment Routing with IPv6
[    0.105776] In-situ OAM (IOAM) with IPv6
[    0.105978] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.108356] 9pnet: Installing 9P2000 support
[    0.117062] List of all partitions:
[    0.117262] No filesystem could mount root, tried:
[    0.117277]
[    0.117571] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    0.117983] Kernel Offset: disabled
[    0.118090] CPU features: 0x00000000,00000802
[    0.118393] Memory Limit: none
[    0.118767] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

注意,这个内核没有initramfs,因此必须有启动参数ROOT才能找到根分区,比如ROOT=/dev/nvme0n1p2.ROOT的值的格式与/etc/fstab的格式相同,可以使用ROOT=LABEL=xxxROOT=UUID=xxxxxxxxxxxxx.如果这个分区可以被内核识别,同时存在/sbin/init,则init被启动.如果没有指定rootfs,或者无法识别ROOT的目标,则会输出:

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

大多数情况下,内核可以直接找到ROOT的分区并启动,但是处于故障维护的考虑,我们可能需要一个initramfs.

关于如何制作initramfs的资料可以参考Gentoo的wiki:Custom Initramfs

编译busybox

busybox将数十个符合POSIX的Unix工具集成到一个不到2M的可执行文件中,非常适合在内存中运行的initramfs环境.

cd $DISTDIR && wget -qO- https://busybox.net/downloads/busybox-1.34.1.tar.bz2 | tar xvj && cd busybox-1.34.1

# 打一个补丁, 否则clang编译出来的程序会直接崩溃
wget -qO- https://github.com/kraj/meta-clang/raw/master/recipes-core/busybox/busybox/0001-Turn-ptr_to_globals-and-bb_errno-to-be-non-const.patch | patch -p1

make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE menuconfig
# 选中Settings -> Don't use /usr 和 Build static binary (no shared libs)
make ARCH=$ARCH CFLAGS="${CFLAGS}" CROSS_COMPILE=$CROSS_COMPILE -j13
mkdir $INITRAMFS/bin && cp busybox $INITRAMFS/bin

验证可以使用.

> file busybox
busybox: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
> qemu-aarch64 busybox uname -m
aarch64

构造initramfs

以root身份运行以下命令

# busybox的mkdir不支持mkdir $INITRAMFS/{bin,dev,proc,sbin,sys}
for i in bin dev proc sbin sys;do
  mkdir $INITRAMFS/$i
done
# cp --archive /dev/{null,console,tty} $INITRAMFS/dev/
for i in null console tty;do
  cp --archive /dev/$i $INITRAMFS/dev/
done

创建$INITRAMFS/init文件:

#!/bin/busybox sh
/bin/busybox --install -s
mount -t devtmpfs devtmpfs /dev
mount -t proc none /proc
mount -t sysfs none /sys
setsid cttyhack sh
poweroff -f

将其设置为可运行文件:chmod +x init

最终的文件列表为:

drwxr-xr-x    - root  ├── bin
.rwxr-xr-x 1.2M root  │  └── busybox
drwxr-xr-x    - root  ├── dev
crw-------  5,1 root  │  ├── console
crw-rw-rw-  1,3 root  │  ├── null
crw-rw-rw-  5,0 root  │  └── tty
.rwxr-xr-x  157 root  ├── init
drwxr-xr-x    - root  ├── proc
drwxr-xr-x    - root  ├── sbin
drwxr-xr-x    - root  └── sys

将initramfs打包进内核

initramfs可以分开打包, 也可以包含在内核内.

如果想分开打包,进入内核设置界面

make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE LLVM=1 LLVM_IAS=1 menuconfig

来到General Setup, 选中Initial RAM filesystem and RAM disk (initramfs/initrd) support, 以及下面想要使用的压缩格式.

ZSTD压缩率最高且解压速度快, 建议实际部署时使用. gzip最简单, 测试时可以用.

cd $INITRAMFS && find . 2>/dev/null | cpio -ov -R root:root -H newc | gzip -9 > ../initramfs.img.gz
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
()    Initramfs source file(s) (NEW)
[*]   Support initial ramdisk/ramfs compressed using gzip (NEW)
[ ]   Support initial ramdisk/ramfs compressed using bzip2
[ ]   Support initial ramdisk/ramfs compressed using LZMA
[ ]   Support initial ramdisk/ramfs compressed using XZ
[ ]   Support initial ramdisk/ramfs compressed using LZO
[ ]   Support initial ramdisk/ramfs compressed using LZ4
[ ]   Support initial ramdisk/ramfs compressed using ZSTD 

使用如下命令打包出initramfs镜像压缩包.

cd $INITRAMFS && find . 2>/dev/null | cpio -ov -R root:root -H newc | gzip -9 > ../initramfs.img.gz

如果想打包进内核, 进入内核设置界面, 在Initramfs source file(s)选择$INITRAMFS的地址

[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/home/han/aarch64-linux-musl/initramfs) Initramfs source file(s)
(0)   User ID to map to 0 (user root) (NEW)
(0)   Group ID to map to 0 (group root) (NEW)
[*]   Support initial ramdisk/ramfs compressed using gzip
[ ]   Support initial ramdisk/ramfs compressed using bzip2
[ ]   Support initial ramdisk/ramfs compressed using LZMA
[ ]   Support initial ramdisk/ramfs compressed using XZ
[ ]   Support initial ramdisk/ramfs compressed using LZO
[ ]   Support initial ramdisk/ramfs compressed using LZ4
[ ]   Support initial ramdisk/ramfs compressed using ZSTD
Built-in initramfs compression mode (Gzip)  ---> 

重新编译内核

make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE -j13

测试

可以在qemu或者真机上测试内核.

> qemu-system-aarch64 -m 64M -M virt -cpu cortex-a53 -kernel ./Image.gz -initrd ./initramfs.img.gz -nographic -append "console=ttyAMA0"
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.15.1-zen+ (han@musl) (clang version 13.0.0, LLD 13.0.0) #115 ZEN SMP Tue Nov 9 19:27:33 CST 2021
[    0.000000] Machine model: linux,dummy-virt
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000043ffffff]
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv0.2 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 16 pages/cpu s34392 r0 d31144 u65536
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: kernel page table isolation disabled by kernel configuration
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16160
[    0.000000] Kernel command line: console=ttyAMA0
[    0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.000000] Memory: 55076K/65536K available (3328K kernel code, 654K rwdata, 412K rodata, 1344K init, 260K bss, 10460K reserved, 0K cma-reserved)
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=1.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] Root IRQ handler: 0xffffffc010169f08
[    0.000000] GICv2m: range[mem 0x08020000-0x08020fff], SPI[80:143]
[    0.000000] arch_timer: cp15 timer(s) running at 62.50MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
[    0.000052] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns
[    0.001858] Console: colour dummy device 80x25
[    0.002812] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=250000)
[    0.002927] pid_max: default: 4096 minimum: 301
[    0.004977] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.005011] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.024230] rcu: Hierarchical SRCU implementation.
[    0.026300] smp: Bringing up secondary CPUs ...
[    0.026386] smp: Brought up 1 node, 1 CPU
[    0.026412] SMP: Total of 1 processors activated.
[    0.026454] CPU features: detected: 32-bit EL0 Support
[    0.026513] CPU features: detected: CRC32 instructions
[    0.027487] CPU: All CPU(s) started at EL1
[    0.027609] alternatives: patching kernel code
[    0.035079] devtmpfs: initialized
[    0.040810] random: get_random_bytes called from 0xffffffc0103dd960 with crng_init=0
[    0.042477] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.043860] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.047242] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.049753] ASID allocator initialised with 65536 entries
[    0.049816] Serial: AMBA PL011 UART driver
[    0.067495] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 47, base_baud = 0) is a PL011 rev1
[    0.075982] printk: console [ttyAMA0] enabled
[    0.092989] vgaarb: loaded
[    0.101630] clocksource: Switched to clocksource arch_sys_counter
[    0.113153] NET: Registered PF_INET protocol family
[    0.114575] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.117043] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
[    0.117523] TCP established hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.117866] TCP bind hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.118189] TCP: Hash tables configured (established 512 bind 512)
[    0.119488] UDP hash table entries: 128 (order: 0, 4096 bytes, linear)
[    0.119748] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes, linear)
[    0.120968] PCI: CLS 0 bytes, default 64
[    0.138685] workingset: timestamp_bits=62 max_order=14 bucket_order=0
[    0.139068] 9p: Installing v9fs 9p2000 file system support
[    0.139586] io scheduler mq-deadline registered
[    0.139796] io scheduler kyber registered
[    0.186347] Unpacking initramfs...
[    0.252316] Freeing initrd memory: 1008K
[    0.274845] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    0.277940] NET: Registered PF_INET6 protocol family
[    0.284542] Segment Routing with IPv6
[    0.284787] In-situ OAM (IOAM) with IPv6
[    0.285422] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.289354] 9pnet: Installing 9P2000 support
[    0.312361] Freeing unused kernel memory: 1344K
[    0.321870] Run /init as init process
/ # uname -a
Linux (none) 5.15.1-zen+ #115 ZEN SMP Tue Nov 9 19:27:33 CST 2021 aarch64 GNU/Linux
/ # ps aux
PID   USER     TIME  COMMAND
    1 0         0:00 {init} /bin/busybox sh /init
    2 0         0:00 [kthreadd]
    3 0         0:00 [rcu_gp]
    4 0         0:00 [rcu_par_gp]
    5 0         0:00 [kworker/0:0-eve]
    6 0         0:00 [kworker/0:0H-ev]
    7 0         0:00 [kworker/u2:0-ev]
    8 0         0:00 [mm_percpu_wq]
    9 0         0:00 [ksoftirqd/0]
   10 0         0:00 [rcu_sched]
   11 0         0:00 [migration/0]
   12 0         0:00 [cpuhp/0]
   13 0         0:00 [kdevtmpfs]
   14 0         0:00 [inet_frag_wq]
   15 0         0:00 [oom_reaper]
   16 0         0:00 [writeback]
   17 0         0:00 [kblockd]
   18 0         0:00 [kworker/0:1-eve]
   19 0         0:00 [kworker/0:1H]
   20 0         0:00 [kworker/u2:1]
   21 0         0:00 [kswapd0]
   22 0         0:00 [mld]
   23 0         0:00 [ipv6_addrconf]
   28 0         0:00 sh
   30 0         0:00 ps aux
/ # free -h
              total        used        free      shared  buff/cache   available
Mem:          56.1M        5.6M       47.1M           0        3.4M       45.8M
Swap:             0           0           0
/ # cat /proc/version
Linux version 5.15.1-zen+ (han@musl) (clang version 13.0.0, LLD 13.0.0) #115 ZEN SMP Tue Nov 9 19:27:33 CST 2021
/ # cat /proc/cpuinfo
processor	: 0
BogoMIPS	: 125.00
Features	: fp asimd aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4
/ # ls /dev/
console      tty14        tty27        tty4         tty52        tty8
full         tty15        tty28        tty40        tty53        tty9
kmsg         tty16        tty29        tty41        tty54        ttyAMA0
null         tty17        tty3         tty42        tty55        urandom
port         tty18        tty30        tty43        tty56        vcs
ptmx         tty19        tty31        tty44        tty57        vcs1
random       tty2         tty32        tty45        tty58        vcsa
tty          tty20        tty33        tty46        tty59        vcsa1
tty0         tty21        tty34        tty47        tty6         vcsu
tty1         tty22        tty35        tty48        tty60        vcsu1
tty10        tty23        tty36        tty49        tty61        vga_arbiter
tty11        tty24        tty37        tty5         tty62        zero
tty12        tty25        tty38        tty50        tty63
tty13        tty26        tty39        tty51        tty7
/ # ls /proc/
1             21            buddyinfo     iomem         self
10            22            bus           ioports       softirqs
11            23            cmdline       irq           stat
12            24            consoles      kmsg          swaps
13            29            cpuinfo       kpagecount    sys
14            3             device-tree   kpageflags    thread-self
15            31            devices       loadavg       timer_list
16            4             diskstats     meminfo       tty
17            5             driver        misc          uptime
18            6             execdomains   mounts        version
19            7             filesystems   net           vmallocinfo
2             8             fs            pagetypeinfo  vmstat
20            9             interrupts    partitions    zoneinfo
/ # ls /sys/
block     class     devices   fs        module
bus       dev       firmware  kernel
/ # exit
[   14.156869] reboot: Power down

按Ctrl-D或者输入exit来关机.