Linux Lab 推出十大精彩使用案例

2021-01-04 開源中國

Linux Lab 是一款即時 Linux 實驗環境,但是其作用遠不止於此!本文從使用案例的角度介紹了另外 10 大難以抗拒 Linux Lab 的理由!

Linux Lab 是一套用於 Linux 內核學習、開發和測試的即時實驗室,可以極速搭建和使用,功能強大,用法簡單!

Linux Lab Boot example

經過 3 年多的開發與迭代,Linux Lab 已經發布了 v0.4-rc3 版,其易用性和功能逐漸強大,非常推薦各位 Linux 內核和嵌入式 Linux 開發者嘗試。

下面列舉了十大使用 Linux Lab 的案例。

學習 C 語言

安裝完以後,如果選擇 bash 登陸方式,會立即進入到 Linux 命令行。

C 語言開發

裡頭已經安裝好了必備的編輯器 vim 和編譯器 gcc,可以直接上手 C 語言開發。

$ tools/docker/bash linux-labubuntu@linux-lab:/labs/linux-lab$ cd examples/c/hello/ubuntu@linux-lab:/labs/linux-lab/examples/c/hello$ gcc -o hello hello.chello.c Makefile README.mdubuntu@linux-lab:/labs/linux-lab/examples/c/hello$ ./helloHello, World!

簡單 C 語言工程管理 Makefile

另外,裡面已經提供了一個簡單的 Makefile 例子,可以直接通過 make 生成 hello.i, hello.s 和 hello.o。

ubuntu@linux-lab:/labs/linux-lab/examples/c/hello$ make hello.iubuntu@linux-lab:/labs/linux-lab/examples/c/hello$ make hello.subuntu@linux-lab:/labs/linux-lab/examples/c/hello$ make hello.o

在這個基礎上,結合任何一本經典的 C 語言書籍,就可以學習基本的語法、算法和 Posix API 用法了。

學習彙編語言和處理器指令集

Linux Lab 不只準備了 x86 的 gcc 編譯器,而且準備了其他幾大主流處理器架構的編譯器,學習各種架構編譯器不在話下,而且可以立即使用 qemu 來執行。

X86 彙編

先來看一段 x86 的彙編:

$ tools/docker/bash linux-labubuntu@linux-lab:/labs/linux-lab$ cd examples/assembly/ubuntu@linux-lab:/labs/linux-lab/examples/assembly$ lsaarch64 arm mips64el mipsel powerpc powerpc64 README.md riscv32 riscv64 x86 x86_64ubuntu@linux-lab:/labs/linux-lab/examples/assembly/x86$ makeas --32 -o x86-hello.o x86-hello.sld -m elf_i386 -o x86-hello x86-hello.o/labs/linux-lab/examples/assembly/x86/x86-helloHello, world!ubuntu@linux-lab:/labs/linux-lab/examples/assembly/x86$ cat x86-hello.s.data # section declarationmsg: .string "Hello, world!\n" len = . - msg # length of our dear string.text # section declaration # we must export the entry point to the ELF linker or .global _start # loader. They conventionally recognize _start as their # entry point. Use ld -e foo to override the default._start:# write our string to stdout movl $len,%edx # third argument: message length movl $msg,%ecx # second argument: pointer to message to write movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel# and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel

ARM 彙編

arm 的也不在話下:

ubuntu@linux-lab:/labs/linux-lab/examples/assembly/arm$ cat arm-hello.s.datamsg: .ascii "Hello, ARM!\n"len = . - msg.text.globl _start_start: /* syscall write(int fd, const void *buf, size_t count) */ mov %r0, $1 /* fd -> stdout */ ldr %r1, =msg /* buf -> msg */ ldr %r2, =len /* count -> len(msg) */ mov %r7, $4 /* write is syscall #4 */ swi $0 /* invoke syscall */ /* syscall exit(int status) */ mov %r0, $0 /* status -> 0 */ mov %r7, $1 /* exit is syscall #1 */ swi $0 /* invoke syscall */ubuntu@linux-lab:/labs/linux-lab/examples/assembly/arm$ makearm-linux-gnueabi-as -o arm-hello.o arm-hello.sarm-linux-gnueabi-ld -o arm-hello arm-hello.oHello, ARM!

RISC-V 彙編

其他架構也可以類似使用,有個別架構,比如 RISC-V,需要先切到 Linux Lab 根目錄下載工具鏈:

$ tools/docker/bash linux-labubuntu@linux-lab:/labs/linux-lab$ubuntu@linux-lab:/labs/linux-lab$ make BOARD=riscv64/virt[ riscv64/virt ]: ARCH = riscv XARCH = riscv64 CPU = any SMP = 4 MEM = 1024M QEMU = v4.0.0 QEMU_US = 1 LINUX = v5.1 BUILDROOT = 2019.05 NETDEV_LIST = virtio NETDEV = virtio SERIAL = ttyS0 NET9PDEV = virtio-9p-device ROOTDEV_LIST = /dev/vda /dev/ram0 /dev/nfs ROOTDEV = /dev/vda FSTYPE = ext2 PORIIMG = fw_jump.elf PKIMAGE = /labs/linux-lab/boards/riscv64/virt/bsp/kernel/v5.1/fw_jump.elf KRN_ADDR = 0x80200000 ORIIMG = arch/riscv/boot/Image KIMAGE = /labs/linux-lab/output/riscv64/linux-v5.1-virt/arch/riscv/boot/Image ROOTFS = /labs/linux-lab/boards/riscv64/virt/bsp/root/2019.05/rootfs.cpio.gz HROOTFS = /labs/linux-lab/boards/riscv64/virt/bsp/root/2019.05/rootfs.ext2 QTOOL = /labs/linux-lab/boards/riscv64/virt/bsp/qemu/v4.0.0/bin/qemu-system-riscv64 CCORI = gnu-mcu-eclipseubuntu@linux-lab:/labs/linux-lab$ make bspDownloading bsp source ...Previous HEAD position was c6c47f0... README: Update usageHEAD is now at e2963d2... buildroot: 2019.05: speed up root buildingubuntu@linux-lab:/labs/linux-lab$ make toolchain[ gnu-mcu-eclipse 8.2.0-2.2-20190521-0004 ]:Remote.: https://github.com/gnu-mcu-eclipse/riscv-none-gcc/releases/download/v8.2.0-2.2-20190521/gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-centos64.tgzLocal..: /labs/linux-lab/prebuilt/toolchains/riscv64/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/binTool...: riscv-none-embed-gccVersion: riscv-none-embed-gcc (GNU MCU Eclipse RISC-V Embedded GCC, 64-bit) 8.2.0

之後同樣可以使用:

ubuntu@linux-lab:/labs/linux-lab$ cd examples/assembly/riscv32ubuntu@linux-lab:/labs/linux-lab/examples/assembly/riscv32$ make... riscv-none-embed-as -o riscv32-hello.o riscv32-hello.s... riscv-none-embed-ld -o riscv32-hello riscv32-hello.oHello Risc-V

免費使用某塊虛擬開發板7 大架構 + 16 塊板子

Linux Lab 已經集成了 7 大架構的 16 塊開發板,平均每個架構支持兩款以上。常用的開發板基本都有了,包括 32 位和 64 位架構基本可以任選。

所有的板子都有:

編譯好的 Qemu 的模擬器

編譯好的 文件系統以及配置文件

編譯好的 內核鏡像、dtb 以及配置文件

可直接啟動到串口的 Qemu 啟動腳本

所有倉庫都可以單獨下載,可以在 Linux Lab 內使用,也可以單獨使用。這裡是已經集成到主線的部分:

ubuntu@linux-lab:/labs/linux-lab$ cat .gitmodules | grep qemu-url = https://gitee.com/tinylab/qemu-aarch64-raspi3/url = https://gitee.com/tinylab/qemu-aarch64-virt.giturl = https://gitee.com/tinylab/qemu-arm-versatilepb.giturl = https://gitee.com/tinylab/qemu-arm-vexpress-a9.giturl = https://gitee.com/tinylab/qemu-i386-pc.giturl = https://gitee.com/tinylab/qemu-mipsel-malta.giturl = https://gitee.com/tinylab/qemu-ppc-g3beige.giturl = https://gitee.com/tinylab/qemu-riscv32-virt.giturl = https://gitee.com/tinylab/qemu-riscv64-virt.giturl = https://gitee.com/tinylab/qemu-x86_64-pc.giturl = https://gitee.com/tinylab/qemu-arm-mcimx6ul-evk.git

任選一塊板子立即啟動

如果要使用模塊板子,可以直接:

$ make BOARD=aarch64/virt$ make bootsudo env PATH=/labs/linux-lab/boards/aarch64/virt/bsp/qemu/v4.0.0/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin qemu-system-aarch64 -M virt -m 1024M -net nic,model=virtio -net tap -device virtio-net-device,netdev=net0,mac=30:d7:8a:81:bc:8a -netdev tap,id=net0 -smp 2 -bios /labs/linux-lab/output/aarch64/uboot-v2019.10-virt/u-boot.bin -no-reboot -device loader,file=tftpboot/env.img,addr=0x49000000 -drive if=pflash,file=tftpboot/pflash.img,format=raw,unit=1 -drive if=none,file=/labs/linux-lab/boards/aarch64/virt/bsp/root/2019.11.1/rootfs.ext2,format=raw,id=virtio-vda -device virtio-blk-device,drive=virtio-vda -nographic -cpu cortex-a57 -serial mon:stdio -machine virt,gic_version=3 -machine type=virt,virtualization=true -d guest_errors -nodefaultsU-Boot 2019.10-dirty (May 10 2020 - 23:59:50 +0800)DRAM: 1 GiBFlash: 128 MiB*** Warning - bad CRC, using default environmentIn: pl011@9000000Out: pl011@9000000Err: pl011@9000000Net:Warning: virtio-net#31 using MAC address from ROMeth0: virtio-net#31Hit any key to stop autoboot: 0## Warning: defaulting to text format## Flattened Device Tree blob at 44000000 Booting using the fdt blob at 0x44000000 Loading Device Tree to 000000007edf3000, end 000000007edf7c95 ... OKStarting kernel ...Booting Linux on physical CPU 0x0000000000 [0x411fd070]Linux version 5.1.0 (ubuntu@linux-lab) (gcc version 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4] (Linaro GCC 7.4-2019.02)) #1 SMP Wed May 6 03:15:08 CST 2020Machine model: linux,dummy-virtearlycon: pl11 at MMIO 0x0000000009000000 (options '')printk: bootconsole [pl11] enabledefi: Getting EFI parameters from FDT:efi: UEFI not found.psci: probing for conduit method from DT.psci: PSCIv0.2 detected in firmware.psci: Using standard PSCI v0.2 function IDspsci: Trusted OS migration not requiredrandom: get_random_bytes called from start_kernel+0xa8/0x4b4 with crng_init=0percpu: Embedded 23 pages/cpu s55000 r8192 d31016 u94208Detected PIPT I-cache on CPU0CPU features: detected: ARM erratum 832075CPU features: detected: GIC system register CPU interfaceCPU features: detected: EL2 vector hardeningBuilt 1 zonelists, mobility grouping on. Total pages: 258048Kernel command line: route=172.17.0.3 iface=eth0 rw fsck.repair=yes rootwait root=/dev/vda earlycon console=ttyAMA0Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)Memory: 1018660K/1048576K available (6140K kernel code, 790K rwdata, 1472K rodata, 832K init, 335K bss, 29916K reserved, 0K cma-reserved)SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1rcu: Hierarchical RCU implementation.rcu: RCU event tracing is enabled.rcu: RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=2.rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0GICv3: GIC: Using split EOI/Deactivate modeGICv3: Distributor has no Range Selector supportGICv3: no VLPI support, no direct LPI supportGICv3: CPU0: found redistributor 0 region 0:0x00000000080a0000arch_timer: cp15 timer(s) running at 62.50MHz (phys).clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 nssched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096nsConsole: colour dummy device 80x25Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=250000)pid_max: default: 32768 minimum: 301Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes)*** VALIDATE proc ****** VALIDATE cgroup1 ****** VALIDATE cgroup2 ***ASID allocator initialised with 32768 entriesrcu: Hierarchical SRCU implementation.EFI services will not be available.smp: Bringing up secondary CPUs ...Detected PIPT I-cache on CPU1GICv3: CPU1: found redistributor 1 region 0:0x00000000080c0000CPU1: Booted secondary processor 0x0000000001 [0x411fd070]smp: Brought up 1 node, 2 CPUsSMP: Total of 2 processors activated.CPU features: detected: 32-bit EL0 SupportCPU features: detected: CRC32 instructionsCPU: All CPU(s) started at EL2alternatives: patching kernel codedevtmpfs: initializedclocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 nsfutex hash table entries: 512 (order: 3, 32768 bytes)DMI not present or invalid.NET: Registered protocol family 16vdso: 2 pages (1 code @ (____ptrval____), 1 data @ (____ptrval____))hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.DMA: preallocated 256 KiB pool for atomic allocationsSerial: AMBA PL011 UART driver9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 40, base_baud = 0) is a PL011 rev1printk: console [ttyAMA0] enabledprintk: console [ttyAMA0] enabledprintk: bootconsole [pl11] disabledprintk: bootconsole [pl11] disabledSCSI subsystem initializedclocksource: Switched to clocksource arch_sys_counterNET: Registered protocol family 2tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes)TCP established hash table entries: 8192 (order: 4, 65536 bytes)TCP bind hash table entries: 8192 (order: 5, 131072 bytes)TCP: Hash tables configured (established 8192 bind 8192)UDP hash table entries: 512 (order: 2, 16384 bytes)UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)NET: Registered protocol family 1RPC: Registered named UNIX socket transport module.RPC: Registered udp transport module.RPC: Registered tcp transport module.RPC: Registered tcp NFSv4.1 backchannel transport module.hw perfevents: enabled with armv8_pmuv3 PMU driver, 5 counters availableworkingset: timestamp_bits=62 max_order=18 bucket_order=0NFS: Registering the id_resolver key typeKey type id_resolver registeredKey type id_legacy registered9p: Installing v9fs 9p2000 file system supportBlock layer SCSI generic (bsg) driver version 0.4 loaded (major 252)io scheduler mq-deadline registeredio scheduler kyber registeredcacheinfo: Unable to detect cache hierarchy for CPU 0virtio_blk virtio0: [vda] 14336 512-byte logical blocks (7.34 MB/7.00 MiB)NET: Registered protocol family 10Segment Routing with IPv6sit: IPv6, IPv4 and MPLS over IPv4 tunneling driverNET: Registered protocol family 17NET: Registered protocol family 159pnet: Installing 9P2000 supportKey type dns_resolver registeredregistered taskstats version 1hctosys: unable to open rtc device (rtc0)EXT4-fs (vda): mounting ext2 file system using the ext4 subsystemEXT4-fs (vda): warning: mounting unchecked fs, running e2fsck is recommendedEXT4-fs (vda): mounted filesystem without journal. Opts: (null)VFS: Mounted root (ext2 filesystem) on device 254:0.devtmpfs: mountedFreeing unused kernel memory: 832KRun /sbin/init as init processEXT4-fs (vda): re-mounted. Opts: block_validity,barrier,user_xattrStarting syslogd: OKStarting klogd: OKRunning sysctl: OKInitializing random number generator: OKSaving random seed: random: dd: uninitialized urandom read (512 bytes read)OKStarting network: eth: eth0, ip: 172.17.0.181, gw: 172.17.0.3OKWelcome to Linux Lablinux-lab login: root## reboot -f

所有默認準備好的文件系統帳號是 root,密碼為空,直接敲擊回車即可進去。大部分板子都可以用 reboot -f 退出,個別板子可能會卡死,可以用 「CTRL+a x」 退出 Qemu。

傳統的 Qemu 啟動腳本:boot.sh

當然,也可以直接用最簡單易懂的 boot.sh 腳本,這個腳本甚至可以在主機下直接使用:

ubuntu@linux-lab:/labs/linux-lab$ cd boards/aarch64/virt/bsp/ubuntu@linux-lab:/labs/linux-lab/boards/aarch64/virt/bsp$ ./boot.shWelcome to Linux Lablinux-lab login: root## reboot -f

不過,boot.sh 可沒 「make boot」 靈活方便。比如說,想通過 tftp 加載鏡像,並通過 nfsboot 加載文件系統,要用 boot.sh 得手動改一堆不是那麼容易理解和上手的參數,特別地,要配置網絡並沒有那麼簡單。

無比優雅的 「make boot」

用 Linux Lab 的 「make boot」 是這麼的優雅:

ubuntu@linux-lab:/labs/linux-lab$ make boot ROOTDEV=/dev/nfs BOOTDEV=tftp

Linux 內核開發

直接使用編譯好的當然不夠酷,得能自己修改內核並編譯內核才行。

編譯 Linux v5.6

加入我們想學習 x86_64 架構上的 Linux v5.6 內核,可以切到 x86_64/pc 這塊板子,然後升級到內核 v5.6:

$ make BOARD=x86_64/pc$ make kernel-clone LINUX_NEW=v5.6$ make kernel-cleanup$ make kernel

編譯其他版本 Linux

如果想用默認的版本,則不需要使用 kernel-clone,查看已經驗證過的內核版本。

$ make list linuxv3.2 v5.0.10 v5.0.21 [v5.1] v5.4 v5.4.29$ make local-config LINUX=v5.4v3.2 v5.0.10 v5.0.21 v5.1 [v5.4] v5.4.29$ make kernel

需要注意的是,kernel-clone 會使用當前板子默認配置的內核配置文件,如果內核版本差異太大,現有配置文件可能不會工作,建議直接從 linux-stable 目錄下複製一份現有配置到 boards/<BOARD>/bsp/configs 目錄下。之後再配置和編譯。

如果是更早的 Linux 版本,可能會涉及到編譯器不兼容,需要修改部分代碼或者調整編譯器版本。

更換編譯器版本

首先我們查看哪些版本可以用,包括內置的版本和外置的版本,內置的版本用 CCORI=internal 指定後,配置 GCC 即可,外部的直接指定 CCORI 進行切換。

查看當前架構支持的編譯器,可以看到暫時沒有配置外部的版本,但是內部的有三個:

$ make gcc-listListing prebuilt toolchain ...[ internal gcc-8 ]:Remote.:Local..:Tool...: gccVersion: gcc (Ubuntu 8.3.0-16ubuntu3~14.04.2) 8.3.0More...: /usr/bin/gcc-4.4 /usr/bin/gcc-4.8 /usr/bin/gcc-8

直接切換:

$ make gcc-switch GCC=4.4

或者更持久的配置:

$ make local-config GCC=4.4

如果要為某個版本配特定 GCC:

$ make local-config GCC[LINUX_v5.6]=8

查看記錄:

$ make local-editLINUX := v5.6GCC := 4.4GCC[LINUX_v5.6] := 8

如果發現某個已經配置好的內核必須用特定 GCC 才能編譯,請往 Linux Lab 發送 PR。

修改代碼後編譯啟動

接著,隨便改一點你想修改的代碼,然後就可以重新編譯並啟動了:

$ git diff init/main.cdiff --git a/init/main.c b/init/main.cindex ee4947a..acd6c71 100644--- a/init/main.c+++ b/init/main.c@@ -815,6 +815,7 @@ asmlinkage __visible void __init start_kernel(void) build_all_zonelists(NULL); page_alloc_init();+ pr_info("Hello Linux\n"); pr_notice("Kernel command line: %s\n", saved_command_line); /* parameters may set static keys */ jump_label_init();$ make kernel$ make boot...Welcome to Linux Lablinux-lab login: root## dmesg | grep Hello[ 0.447766] Hello Linux# reboot -f[ 107.481353] reboot: Restarting system[ 107.482477] reboot: machine restart

堪稱完美,我們改動的地方生效了,日誌被列印了出來。

單獨編譯某個文件並查看效果

比如說剛剛修改了 init/main.c,希望立即查看預處理的結果、彙編以及二進位文件。

預處理的結果:

$ make kernel-run init/main.i$ grep Hello -ur output/x86_64/linux-v5.6-pc/init/main.i printk("\001" "6" "Hello Linux\n");

彙編:

$ make kernel-run init/main.s$ grep -A5 -B1 Hello -ur output/x86_64/linux-v5.6-pc/init/main.s.LC27: .string "\0016Hello Linux\n".LC28: .string "\0015Kernel command line: %s\n".LC29: .string "Booting kernel".LC30:-- call page_alloc_init ## /labs/linux-lab/linux-stable/init/main.c:818: pr_info("Hello Linux\n"); movq $.LC27, %rdi #, call printk ## /labs/linux-lab/linux-stable/init/main.c:819: pr_notice("Kernel command line: %s\n", saved_command_line); movq saved_command_line(%rip), %rsi # saved_command_line, movq $.LC28, %rdi #,

目標文件:

$ make kernel-run init/main.o$ ls output/x86_64/linux-v5.6-pc/init/main.o

Linux 內核模塊開發

要學習和開發一個 Linux 內核模塊是如此的簡單。

編譯一個準備好的 hello 模塊

在 examples/hello 下面已經準備了一個極其簡單的內核模塊,直接編譯:

$ make module module=helloBuilding module: hello ...LOG: m=hello ; M=/labs/linux-lab/modules/hello Current using module is /labs/linux-lab/modules/hello. to compile modules under linux-stable, use 'make kernel-modules'.make O=/labs/linux-lab/output/x86_64/linux-v5.6-pc -C linux-stable ARCH=x86 LOADADDR= CROSS_COMPILE= V= CONFIG_INITRAMFS_SOURCE= -j4 modules_prepare GEN Makefile DESCEND objtool CALL /labs/linux-lab/linux-stable/scripts/atomic/check-atomics.sh CALL /labs/linux-lab/linux-stable/scripts/checksyscalls.sh CC [M] /labs/linux-lab/modules/hello/hello.o MODPOST 1 modules CC [M] /labs/linux-lab/modules/hello/hello.mod.o LD [M] /labs/linux-lab/modules/hello/hello.ko

修改、編譯並簡單測試該模塊

修改:

$ ubuntu@linux-lab:/labs/linux-lab$ git diff modules/hello/diff --git a/modules/hello/hello.c b/modules/hello/hello.cindex 59f1c55..2321857 100644--- a/modules/hello/hello.c+++ b/modules/hello/hello.c@@ -4,14 +4,14 @@ static int __init my_hello_init(void) {- pr_info("hello module init\n");+ pr_info("mymodule init\n"); return 0; } static void __exit my_hello_exit(void) {- pr_info("hello module exit\n");+ pr_info("mymodule exit\n"); } module_init(my_hello_init);

編譯:

ubuntu@linux-lab:/labs/linux-lab$ make module module=hello

啟動後簡單驗證:

ubuntu@linux-lab:/labs/linux-lab$ make module-install module=helloubuntu@linux-lab:/labs/linux-lab$ make root-rebuildWelcome to Linux Lablinux-lab login: root## modprobe hello[ 15.777975] hello: loading out-of-tree module taints kernel.[ 15.811822] mymodule init## modprobe -r hello[ 27.279818] mymodule exit# reboot -f[ 37.218398] reboot: Restarting system[ 37.218612] reboot: machine restart

自動驗證(無需手動安裝,直接取代上述所有命令):

ubuntu@linux-lab:/labs/linux-lab$ make test module=hello ROOTDEV=/dev/ram0

如果有些動作做過了,想直接測試,更簡單:

ubuntu@linux-lab:/labs/linux-lab$ make test module=hello ROOTDEV=/dev/ram0 FEATURE_INIT=0

Linux 內核特性開發

先列出當前已經驗證過的 feature:

ubuntu@linux-lab:/labs/linux-lab$ make list features[ feature/linux ]: + 9pnet - config - config.aarch64.virt.broken - config.pc - config.versatilepb + cmdline_size - patch.sh - README.md + core - debug * config - initrd * config - module * config - nfsroot * config * README.md + ftrace - v2.6.36 * config * env.g3beige * env.malta * env.pc * env.versatilepb - v2.6.37 * config * env.g3beige + gcs - v2.6.36 * config * env.g3beige * env.malta * env.pc * env.versatilepb * patch + kft - v2.6.36 * config * config.pc * env.malta * env.pc * patch + rt - config - v5.0.21 * download.sh * patch-5.0.21-rt16.patch * patch-5.0.21-rt16.patch.xz - v5.2 * download.sh * patch-5.2-rt1.patch * patch-5.2-rt1.patch.gz + uksm - v2.6.38 * config * patch * version

接著來跑一下 rt preempt 特性:

ubuntu@linux-lab:/labs/linux-lab$ make BOARD=x86_64/pcubuntu@linux-lab:/labs/linux-lab$ make local-config LINUX=v5.0.21ubuntu@linux-lab:/labs/linux-lab$ make kernel-cleanupubuntu@linux-lab:/labs/linux-lab$ make kernel-defconfigubuntu@linux-lab:/labs/linux-lab$ make feature feature=rtubuntu@linux-lab:/labs/linux-lab$ make kernel-olddefconfigubuntu@linux-lab:/labs/linux-lab$ make kernelubuntu@linux-lab:/labs/linux-lab$ make boot[ 26.744772] 001: Run /init as init processStarting syslogd: OKStarting klogd: OKInitializing random number generator... [ 31.520793] 001: random: dd: uninitialized urandom read (512 bytes read)done.Starting network: [ 36.352869] 002: ifconfig (1146) used greatest stack depth: 13904 bytes lefteth: eth0, ip: 172.17.0.61, gw: 172.17.0.3[ 37.091929] 001: ip (1150) used greatest stack depth: 13600 bytes leftOKWelcome to Linux Lablinux-lab login: root## dmesg | grep -i Preempt[ 0.000000] 000: Linux version 5.0.21-rt16+ (ubuntu@linux-lab) (gcc version 8.3.0 (Ubuntu 8.3.0-16ubuntu3~14.04.2)) #2 SMP PREEMPT RT Fri May 15 04:38:39 CST 2020[ 3.539891] 000: rcu: Preemptible hierarchical RCU implementation.

Uboot 開發支持 Uboot 的板子

當前已經驗證可以在 arm32 和 arm64 位的板子上進行 Uboot 開發。已經驗證過的板子有:

arm/versatilepb

arm/vexpress-a9

aarh64/virt

啟動時禁用 Uboot

默認情況下,會直接啟動 Uboot,然後加載內核再啟動。

如果想直接啟動內核:

ubuntu@linux-lab:/labs/linux-lab$ make BOARD=arm/vexpress-a9ubuntu@linux-lab:/labs/linux-lab$ make boot U=0

啟動時切換不同的設備加載內核等鏡像

ubuntu@linux-lab:/labs/linux-lab make boot BOOTDEV=mmc mkfs.fat 3.0.26 (2014-03-07) sudo env PATH=/labs/linux-lab/boards/arm/vexpress-a9/bsp/qemu/v4.1.1/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin qemu-system-arm -M vexpress-a9 -m 1024M -net nic,model=lan9118 -net tap -smp 1 -kernel /labs/linux-lab/output/arm/uboot-v2020.04-vexpress-a9/u-boot -no-reboot -drive if=sd,file=tftpboot/sd.img,format=raw,id=sd0 -drive if=pflash,file=tftpboot/pflash.img,format=raw -nographic

U-Boot 2020.04-dirty (May 06 2020 - 16:19:09 +0800)DRAM: 1 GiBWARNING: Caches not enabledFlash: 128 MiBMMC: MMC: 0*** Warning - bad CRC, using default environmentIn: serialOut: serialErr: serialNet: smc911x-0Hit any key to stop autoboot: 0## Warning: defaulting to text format4471936 bytes read in 1360 ms (3.1 MiB/s)1430238 bytes read in 442 ms (3.1 MiB/s)14087 bytes read in 22 ms (625 KiB/s)## Booting kernel from Legacy Image at 60003000 ... Image Name: Linux-5.1.0 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4471872 Bytes = 4.3 MiB Load Address: 60003000 Entry Point: 60003000 Verifying Checksum ... OK## Loading init Ramdisk from Legacy Image at 60900000 ... Image Name: Image Type: ARM Linux RAMDisk Image (uncompressed) Data Size: 1430174 Bytes = 1.4 MiB Load Address: 00000000 Entry Point: 00000000 Verifying Checksum ... OK## Flattened Device Tree blob at 60500000 Booting using the fdt blob at 0x60500000 Loading Kernel Image Loading Ramdisk to 7fd18000, end 7fe7529e ... OK Loading Device Tree to 7fd11000, end 7fd17706 ... OKStarting kernel ...Booting Linux on physical CPU 0x0Linux version 5.1.0 (ubuntu@524b6f3a0481) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-12ubuntu1)) #3 SMP Thu May 30 08:44:37 UTC 2019CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387dCPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache...

修改、編譯並啟動 Uboot

默認先編譯一遍,會自動下載、配置和編譯:

ubuntu@linux-lab:/labs/linux-lab$ make uboot

修改代碼:

ubuntu@linux-lab:/labs/linux-lab$ cd u-bootubuntu@linux-lab:/labs/linux-lab$ git diffdiff --git a/common/main.c b/common/main.cindex 3a657c3..cd32bc5 100644--- a/common/main.c+++ b/common/main.c@@ -48,6 +48,8 @@ void main_loop(void) cli_init();+ printf("Hello Uboot\n");+ if (IS_ENABLED(CONFIG_USE_PREBOOT)) run_preboot_environment_command();

編譯並啟動,啟動過程中立即按下任意鍵進入 Uboot 命令行:

ubuntu@linux-lab:/labs/linux-lab$ make bootsudo env PATH=/labs/linux-lab/boards/arm/vexpress-a9/bsp/qemu/v4.1.1/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin qemu-system-arm -M vexpress-a9 -m 1024M -net nic,model=lan9118 -net tap -smp 1 -kernel /labs/linux-lab/output/arm/uboot-v2020.04-vexpress-a9/u-boot -no-reboot -drive if=pflash,file=tftpboot/pflash.img,format=raw -nographicU-Boot 2020.04-dirty (May 15 2020 - 02:46:50 +0800)DRAM: 1 GiBWARNING: Caches not enabledFlash: 128 MiBMMC: MMC: 0*** Warning - bad CRC, using default environmentIn: serialOut: serialErr: serialNet: smc911x-0Hello Uboot <-- 這裡有列印我們添加的字符串Hit any key to stop autoboot: 0=>=> resetresetting ...

玩轉文件系統通過 Buildroot 構建文件系統

目前已經內置支持通過 Buildroot 編譯文件系統,當然,也可以用 Busybox 來自己製作。

比如說 aarch64/virt,已經支持到 2019.11.1,可以直接切過去編譯:

ubuntu@linux-lab:/labs/linux-lab$ make BOARD=aarch64/virtubuntu@linux-lab:/labs/linux-lab$ make list root[2016.05] 2019.11.1ubuntu@linux-lab:/labs/linux-lab$ make local-config BUILDROOT=2019.11.1tools/board/config.sh BUILDROOT=2019.11.1 /labs/linux-lab/boards/arm/vexpress-a9/.labconfig v5.1;BUILDROOT := 2019.11.1 /labs/linux-lab/boards/arm/vexpress-a9/.labconfigubuntu@linux-lab:/labs/linux-lab$ make list root2016.05 [2019.11.1]ubuntu@linux-lab:/labs/linux-lab$ make root

調整配置:

ubuntu@linux-lab:/labs/linux-lab$ make root-menuconfig

調整 Busybox 配置:

ubuntu@linux-lab:/labs/linux-lab$ make root-run busybox-menuconfig

通過 Linux Lab 運行 mini Ubuntu

同樣以 aarch64/virt 為例:

ubuntu@linux-lab:/labs/linux-lab$ make BOARD=aarch64/virt

下載一份 mini 版本的 Ubuntu:

$ mkdir tmp && cd tmp$ wget -c https://rcn-ee.com/rootfs/eewiki/minfs/ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz$ tar Jxf ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz$ cd ubuntu-20.04-minimal-armhf-2020-05-10$ mkdir rootfs$ tar xf armhf-rootfs-ubuntu-focal.tar -C rootfs/

然後以 nfsboot 的方式加載,這裡先來刪除掉 root 的密碼(當前 ubuntu 帳號密碼無法登陸):

$ make boot ROOTDIR=$PWD/tmp/ubuntu-20.04-minimal-armhf-2020-05-10/rootfs/ ROOTDEV=/dev/nfs XKCLI="init=/bin/bash" U=0root # passwd -d root

接著啟動並用 root 登陸:

$ make boot ROOTDIR=$PWD/tmp/ubuntu-20.04-minimal-armhf-2020-05-10/rootfs/ ROOTDEV=/dev/nfs U=0...Ubuntu 20.04 LTS arm ttyAMA0default username:password is [ubuntu:temppwd]arm login: rootLast login: Thu Jan 1 00:01:44 UTC 1970 on ttyAMA0root@arm:~#root@arm:~#

Uboot 和 Linux 調試Uboot 調試

已經提前配置好了 gdb 調試腳本, 可以直接調試 Uboot。

開一個終端:

$ tools/docker/bash linux-labubuntu@linux-lab:/labs/linux-lab$ make debug uboot

根據上一個提示,再開一個:

$ tools/docker/bash linux-labubuntu@linux-lab:/labs/linux-lab$ env PATH=/labs/linux-lab/prebuilt/toolchains/aarch64/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin aarch64-linux-gnu-gdb /labs/linux-lab/output/aarch64/uboot-v2019.10-virt/u-boot(gdb) btGNU gdb (Linaro_GDB-2019.02) 8.2.1.20190122-gitReading symbols from /labs/linux-lab/output/aarch64/uboot-v2019.10-virt/u-boot...done.Waiting for 1 secs...Executing gdb commands in local .gdbinit ... my own script(gdb) target remote :12340xffffff80100876dc in ?? ()(gdb) break _startBreakpoint 1 at 0x0: file /labs/linux-lab/u-boot/arch/arm/cpu/armv8/start.S, line 31.gdb bt#0 0xffffff80100876dc in ?? ()#1 0x0000000000000070 in save_boot_params_ret () at /labs/linux-lab/u-boot/arch/arm/cpu/armv8/start.S:117Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Linux 調試

也能類似直接調試內核:

ubuntu@linux-lab:/labs/linux-lab$ make debug kernel

如果沒有打開調試選項:

ubuntu@linux-lab:/labs/linux-lab$ make feature feture=debugubuntu@linux-lab:/labs/linux-lab$ make kernel-olddefconfigubuntu@linux-lab:/labs/linux-lab$ make kernelubuntu@linux-lab:/labs/linux-lab$ make debug kernel

靈活多樣的登陸方式本地登陸

以上都是用 tools/docker/bash 在本地登陸,大部分實驗都能開展,但是跟圖形相關的,比如 LCD 顯示這些,就需要 vnc 登陸。

$ sudo apt-get install -y vinagre$ tools/docker/vnc linux-labLOG: VNC login information: VNC Clients: vinagre xvnc4viewer gvncviewer xtightvncviewer VNC Server: 172.17.0.3 Normal Password: ****** Viewonly Password: ******Available VNC Clients: 1 vinagre 2 xvnc4viewer 3 gvncviewer 4 xtightvncviewerLOG: Choose the vnc client: 1 1 vinagreLOG: Running 'vinagre --vnc-scale --geometry 800x600 172.17.0.3'

之後,vinagre 啟動並彈出密碼輸入框,直接粘貼即可。

遠程登陸

如果想在伺服器上運行 Linux Lab,那麼啟動完,需要獲取到伺服器的外網 IP 地址,配置到 .host_name 即可。

webssh 登陸方式:

$ echo x.y.z.i > .host_name$ tools/docker/webssh linux-labLOG: Please login via ssh client with: SSH_IP: 172.17.0.3 SSH_PORT: 22 User: ubuntu Password: ****** Workdir: //labs/linux-labLOG: Or access via web browser: http://x.y.z.i:4433?ssh=ssh://ubuntu:******@172.17.0.3:22

webvnc 登陸方式:

$ tools/docker/webvnc linux-labPlease login via VNC Client with: IP: 172.17.0.3 User: 7827c9 (Only for noVNC) Password: ****** (Normal) Password: ****** (View)Login for noVNC web client: * Normal: http://x.y.z.i:6080/?u=******&p=****** * View: http://x.y.z.i:6080/?r=************Login for local VNC clients: * IP: 172.17.0.3 * Normal: ****** * View: ******The Other Login methods: * Bash: tools/docker/bash linux-lab * SSH: tools/docker/ssh linux-lab * WebSSH: tools/docker/webssh linux-labNote: Please make sure network available outside and then replace 'localhost' with the external ip or domain name. Then 'echo $ip > .host_name' or 'echo $domain_name > .host_name'Note: firefox, safari and edge work, but google chrome web browser is preferable.

相關焦點

  • 十大使用 Linux Lab 的理由 - OSCHINA - 中文開源技術交流社區
    下面列舉了十大使用 Linux Lab 的理由。省時:節省數周的環境搭建時間無論是新人還是有經驗的老手,搭建 Linux 的學習和實驗環境都是比較費時費力的,一方面要安裝基礎系統,一方面要下載各種交叉編譯工具,有時候還要去下載最新的原始碼。
  • Linux Lab 發布 v0.2-rc2,支持實時 Linux v5.2 開發
    Linux Lab 是一套用於 Linux 內核學習、開發和測試的即時實驗室,可以極速搭建和使用,功能強大,用法簡單!
  • Linux Lab 發布 v0.6-rc2,新增首塊真實硬體開發板
    本次合計 64 筆變更:// linux lab$ git log --pretty=oneline v0.6-rc1..v0.6-rc2 | wc -l57// cloud lab$ git log --pretty=oneline v0.4-rc1..v0.4-rc2 | wc -l7本次主要更新如下:Cloud Lab
  • Linux Lab 發布 v0.4-rc2,新增第 16 塊開發板
    本次合計 58 筆變更:// cloud lab$ git log --oneline v0.2-rc2..v0.2-rc3 | wc -l11// linux lab$ git log --oneline v0.4-rc1..v0.4-rc2 | wc -l47本次關鍵更新如下: 新增第 16 塊開發板
  • Linux Lab v0.5 正式發布,功能強大,用法簡單
    本次合計 204 筆變更:// linux lab$ git log --pretty=oneline v0.4..v0.5 | wc -l144// cloud lab$ git log --pretty=oneline v0.2..HEAD | wc -l60本次有 4 位同學發起了 PR 並被 Merge,另有接近 10
  • Linux Lab 發布 v0.3,簡化操作接口並發布首份中文手冊
    Linux Lab 是一套用於 Linux 內核學習、開發和測試的即時實驗室,可以極速搭建和使用,功能強大,用法簡單!
  • Linux Lab 發布 v0.2 正式版,被某線上課程全程採用
    Linux Lab 是一套用於 Linux 內核學習、開發和測試的即時實驗室,可以極速搭建和使用,功能強大,用法簡單!
  • 基於linux的十大作業系統排名
    基於linux的十大作業系統排名 Win7系統之家 發表於 2020-07-10 16:23:27   基於linux內核開源的特性,並隨著linux的不斷發展,各種基於
  • 軟體測試工程師的 Linux 十大場景命令使用
    由於Linux在伺服器領域應用非常廣泛,有很多開源和成熟的軟體,目前大多數的應用後臺都是部署在linux不同崗位職級,對於linux能力要求也不相同,如果你是初級測試工程師,那麼有可能只需要命令查看日誌,分析bug原因。如果你是中級工程師,則需要在linux環境搭建各種測試環境,包括各種應用程式,應用依賴的中間件,以及測試工具軟體等。
  • 網站改版十大精彩案例分享
    ,那麼有哪些網站改版案例值得我們借鑑與學習呢?Web設計師Mohammad Moradi曾經發表博文《An Exploration of Website Redesigns: Tips and Examples》,文中分享了網站改版的十大精彩案例。
  • linux技術談|linux系統內核優化案例之網絡服務參數
    linux系統是一個何以做伺服器,還可以做工作站,更是嵌入式設備的功臣,今天的地球科技幾乎全部都搭建在linux系統之上。當然在桌面護作業系統領域,linux系統的ubuntu等等一批優秀方案正在成為windows現macos的掘墓者。無所不能的linux系統,在作為不同系統出現時,系統參數的個性化設置就成為linux調優的關鍵手段。
  • 不吹不黑,Jupyter Lab 3.0客觀使用體驗
    圖1那麼目前的jupyter lab好用嗎?是否還存在bug?適合直接升級使用嗎?今天的文章就將通過我的真實使用體驗,來認識jupyter lab3.0。2 jupyter lab 3.0使用體驗為了不幹擾現有的環境,我們通過以下代碼創建新的環境,並安裝最新穩定版本的jupyter lab:conda create -n temp python=3.7 -yconda activate temppip install jupyterlab -U 這樣我們的
  • Linux下查看內存使用情況的多種方法
    0 kBSwapTotal: 0 kBSwapFree: 0 kBDirty: 32 kBWriteback: 0 kBAnonPages: 41088 kBMapped: 35936 kBShmem: 33080 kBSlab
  • 高校攜手央媒推出「2020年中國網絡理政十大創新案例」
    12月28 日,人民日報《民生周刊》雜誌社、復旦發展研究院和復旦大學新聞學院共同發布了「2020年中國網絡理政十大創新案例」,入選的十大創新案例分別是安徽馬鞍山發布、成都溫江市民之聲、廣西南寧武鳴區「壯鄉紅雲」智慧黨建平臺、寧波鄞州178網絡社會柔性治理、河南省政府網站統一技術平臺、網上山東文聯
  • 「2020年度全國對外傳播十大優秀案例」發布,寧波首次獲獎
    會上發布了「2020年度對外傳播十大優秀案例」,並舉行頒獎儀式,中宣部部務會議成員、國務院新聞辦副主任郭衛民,海南省委常委、宣傳部部長肖鶯子等領導為獲獎單位頒發了證書。「對外傳播十大優秀案例」頒獎現場其中,寧波市委宣傳部報送的《「藝術振興鄉村」藉助民間平臺——寧波打造中外藝術家的國際家園》從全國參選的110多個案例中脫穎而出,成功入選「2020年度對外傳播十大優秀案例」,這也是寧波首次獲得該項榮譽。
  • 2020年中國網絡理政十大創新案例發布,隨申碼入選
    記者 黃景源2020年12月28日,「2020年中國網絡理政十大創新案例」發布。入選的十大創新案例分別是安徽馬鞍山發布、成都溫江市民之聲、廣西南寧武鳴區「壯鄉紅雲」智慧黨建平臺、寧波鄞州178網絡社會柔性治理、河南省政府網站統一技術平臺、網上山東文聯、隨申碼、浙江安吉基於融媒體優勢的數字鄉村建設、深圳智慧黨建和珠海橫琴企業專屬網頁。
  • 2020年中國網絡理政十大創新案例發布
    中國山東網-感知山東12月29日訊 2020年12月28日,「2020年中國網絡理政十大創新案例」發布。入選的十大案例由人民日報《民生周刊》雜誌社、復旦發展研究院傳播與國家治理研究中心和復旦大學新聞學院共同發布,創新案例由中央媒體和部屬高校聯手評選推出。
  • Linux終端的使用
    也就是說終端就是為主機提供了人機接口,每個人都通過終端使用主機的資源。終端有字符終端和圖形終端兩種模式。在linux的圖形環境下,我們可以通過滑鼠點擊來完成所有的管理任務,這是圖形界面終端,另外一種就是文本界面的終端,在這個界面的終端下我們可以使用linux命令來控制系統完成響應的工作,而這個文本終端也是伺服器常用的模式。
  • linux實戰案例-讓你的awk命令更上一層樓
    #linux知識匯總與分享#今天分享一下awk常用的幾個功能案例第一步:創建幾個文件任意即可第二步:執行命令ls -l查看當前目錄下的文件組成如下圖所示 :第一個問題是:需要取出來文件的名稱和更新的時間點並用逗號隔開執行下面的命令即可:ls -l|awk '{print $8","$9}'如下圖所示
  • 專注成年人隱形牙齒矯正 xixilab讓你悄悄變美
    如何保證高品質的同時,推出讓大部分人都能承擔的價格,還能減少來回拜訪診所時間的隱形矯正高性價比體驗?xixilab隱形牙齒矯正給出的解決方式是:採用專業團隊及Direct-to-customer模式(品牌直營模式),拒絕中間商,直接面向用戶提供隱形矯正產品,比市場同類產品價格低65%左右的同時,堅持使用具有高透明度,抗裂、抗染性能的CFDA認證的高分子材質。