想让linux内核代码跑起来,得先搭建编译和运行代码的环境。
linux代码尽量在linux环境下编译,以减少不必要的麻烦,我选择的是ubuntu-18.04:
1、linux源码下载
我们依旧使用5.4版本的linux,其下载链接:https://codeload.github.com/torvalds/linux/tar.gz/refs/tags/v5.4
并将源码放置如下文件,为了方便后续管理,我在gitee上创建了一个仓库,为自己后续阅读源码添加注释做准备。
/home/damon/00_code/02_gitee/linux_5.4/linux-5.42、编译内核源码
2.1 选择编译工具
ubuntu本身自带gcc编译器,不过是针对x86平台的,我们现在要编译arm架构的代码,也就是在x8平台上编译arm架构的工具,叫做arm gcc交叉编译器。
我将其解压放置在以下目录:
/usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf2.2 编译配置
基于arm架构的配置,我们选择*./arch/arm/configs/vexpress_defconfig*配置。
直接上编译脚本:
注意事项:如果你的环境是第一次配置,第一次编译的时候大概率会出错,按照错误提示按照依赖工具即可继续编译。
# 根据个人存放的linux源码目录,修改成自己的目录路径cd /home/damon/00_code/02_gitee/linux_5.4/linux-5.4# 清理工程make arch=arm cross_compile=arm-none-linux-gnueabihf- distclean# 配置文件选择:./arch/arm/configs/vexpress_defconfigmake arch=arm cross_compile=arm-none-linux-gnueabihf- vexpress_defconfig# 打开图形配置界面,我们选择默认配置make arch=arm cross_compile=arm-none-linux-gnueabihf- menuconfig
2.3 编译内核
编译内核时,执行如下命令:
# -j8,可以根据实际核数修改,可以提速编译make arch=arm cross_compile=arm-none-linux-gnueabihf- -j8编译成功后,我们可以得到内核镜像文件和设备树文件。内核镜像文件就是我们要跑代码的执行文件,设备树文件就是内核启动后加载它并生成设备节点的文件。
得到的内核镜像文件叫 zimage ,放在如下路径:
/home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot
同时,对应vexpress_defconfig配置下生成的设备树文件:vexpress-v2p-ca9.dtb
内核编译好了,如何将它启动呢?
3、如何启动内核
一般地,学习嵌入式linux,手头上要有一块开发板,一个支持linux开发的开发板少则几百块,贵则上千块。
如果你只是想玩一玩,看一看,完全没必要花这些钱,那么没有开发板该如何启动linux内核呢?
我们可以采用 qemu搭建运行环境 。
qemu是“quick emulation”的缩写,是一个用c语言编写的开源虚拟化软件。它可以模拟硬件,在指定的硬件平台上搭建运行开发环境。
我们暂时无需知道其工作原理,直接拿来安装使用。
3.1 qemu安装
安装qemu工具
sudo apt-get install qemu测试qemu是否安装成功:
qemu起kernel
现在我们有了kernel镜像文件和设备树文件,我们按照qemu的指令启动:
qemu-system-arm -m vexpress-a9 -m 512m -kernel /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/zimage -dtb /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append console=ttyama0启动日志:
省略......cpu: 0 pid: 1 comm: swapper/0 not tainted 5.4.0+ #1hardware name: arm-versatile express[] (unwind_backtrace) from [] (show_stack+0x10/0x14)[] (show_stack) from [] (dump_stack+0x90/0xa4)[] (dump_stack) from [] (panic+0x110/0x310)[] (panic) from [] (mount_block_root+0x204/0x2b4)[] (mount_block_root) from [] (mount_root+0x124/0x148)[] (mount_root) from [] (prepare_namespace+0x154/0x198)[] (prepare_namespace) from [] (kernel_init+0x8/0x110)[] (kernel_init) from [] (ret_from_fork+0x14/0x2c)exception stack(0x9e493fb0 to 0x9e493ff8)3fa0: 00000000 00000000 00000000 000000003fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000003fe0: 00000000 00000000 00000000 00000000 00000013 00000000---[ end kernel panic - not syncing: vfs: unable to mount root fs on unknown-block(0,0) ]---看最后一行:启动到一半出错了,kernel painc!!!
看到panic,慌不慌 ?不过kernel会将panic的原因也打印出来:unable to mount root fs
不能挂在到rootfs上,什么是rootfs呢?没有它,我们该如何做一个呢?
4、 什么是rootfs?
root fs的中文名叫根文件系统。
文件我们好理解,比如我们常见的office文件、图片、视频、压缩包等等都叫文件。
文件系统可以理解为能解析识别这些文件的文件。
昨天我老婆下载了一个压缩包,解压出来发现一个jar文件windows无法识别,这时候我们就要安装java jdk,我们可以粗略地将java jdk叫做能解析jar文件的文件系统(这个比喻不太恰当)。
那什么是根呢?就是linux内核启动所挂载的第一个文件系统,所以这个根字也体现了它的重要性!
一句话总结:rootfs是linux内核启动挂载的第一个文件系统,系统引导启动程序会在根文件系统挂载之后,从中把一些基本的初始化脚本和服务等加载到内存中去运行。
4.1 如何制作一个rootfs
制作rootfs我们要借用一个工具:busybox,忙碌盒子,这个盒子会提供大量linux命令和工具的软件。
busybox的官网地址为: https://busybox.net/ ,最新的版本已经达到1.36.0。
我们不追求最新,因为最新的往往会存在一些兼容性或未知bug,使用我之前用过的1.32.0版本,下载链接:https://busybox.net/downloads/busybox-1.32.0.tar.bz2
解压、配置、编译busybox和编译linux的流程差不多,此处就直接贴脚本了:
cd /home/damon/00_code/02_gitee/busy_boxtar -vxjf busybox-1.32.0.tar.bz2/home/damon/00_code/02_gitee/busy_box/busybox-1.32.0# 手动修改cross_compile和archmake defconfigmake menuconfig
配置完后编译
make# 编译好的东西,我把它安装到 /home/damon/00_code/02_gitee/busy_box/rootfs目录下make install config_prefix=/home/damon/00_code/02_gitee/busy_box/rootfs安装完毕,文件目录显示如下:
可以看到rootfs中有3个文件夹和一个链接文件,具体作用先不展开,此时busybox的工作就完成了,但是此时的rootfs还不能使用,还缺少一些东西,接下来继续补充。
cd /home/damon/00_code/02_gitee/busy_box/rootfs# 创建lib目录,并添加库文件(这些库文件都是从gcc中获取的)mkdir libcd /usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc/libcp *so* /home/damon/00_code/02_gitee/busy_box/rootfs/lib/ -dcd /usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libcp *so* *.a /home/damon/00_code/02_gitee/busy_box/rootfs/lib/ -d# 向usr/lib目录添加库文件cd /usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc/usr/libcp *so* *.a /home/damon/00_code/02_gitee/busy_box/rootfs/usr/lib/ -d# 创建其他文件目录cd /home/damon/00_code/02_gitee/busy_box/rootfsmkdir dev proc mnt sys tmp etc root此时一个可以使用的rootfs便制作完成了,rootfs目录如下图所示:
4.2 rootfs如何使用呢?
rootfs一般放到sd卡或者磁盘中,让内核去读取启动。我手头上没有sd卡,在pc上划出一块磁盘又比较浪费。我们就制作一个sd卡镜像,它是为qemu创建的虚拟sd卡。执行脚本如下:
cd /home/damon/00_code/02_gitee# 制作rootfs.ext4.img文件dd if=/dev/zero of=rootfs.ext4.img bs=1m count=500# 图片截取的是32m,后面实际应用时,发现32m不够用,就修改成了500m# 格式化mkfs.ext4 rootfs.ext4.img
# 将rootfs.ext4.img挂载到/mnt/rootfsmkdir -p /mnt/rootfsmount -t ext4 -o loop rootfs.ext4.img /mnt/rootfs# 将rootfs内所有文件拷贝至rootfs.ext4.imgcp -a /home/damon/00_code/02_gitee/busy_box/rootfs/* /mnt/rootfs/# 卸载umount /mnt/rootfs# 此时得到一个装有rootfs的镜像/home/damon/00_code/02_gitee/rootfs.ext4.img现在rootfs做好了,我们去修复上面的panic.
5、 重新启动kernel
我们在原有的qemu命令基础上指定rootfs的镜像文件,重新启动:
qemu-system-arm -m vexpress-a9 -m 512m -kernel /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/zimage -dtb /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -sd /home/damon/00_code/02_gitee/rootfs.ext4.img -append root=/dev/mmcblk0 rw console=ttyama0启动日志如下:
之前的kernel panic没有了,但是又有新的告警了,一般错误是必须要修复的,而告警内容是可以忽略的,除非影响到了使用和性能。
当前告警在循环打印无法打开,/dev/tty2 /dev/tty3 /dev/tty4, 看到这个我们显然知道是缺少串口设备,按照如下脚本添加,并更新镜像文件。
sudo mknod dev/tty2 c 5 1sudo mknod dev/tty3 c 5 1sudo mknod dev/tty4 c 5 1此时linux操作系统起来了,完整的详细的启动日志如下:
damon@ubuntu:~/00_code/02_gitee$damon@ubuntu:~/00_code/02_gitee$damon@ubuntu:~/00_code/02_gitee$ qemu-system-arm -m vexpress-a9 -m 512m -kernel /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/zimage -dtb /home/damon/00_code/02_gitee/linux_5.4/linux-5.4/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -sd /home/damon/00_code/02_gitee/rootfs.ext4.img -append root=/dev/mmcblk0 rw console=ttyama0warning: image format was not specified for '/home/damon/00_code/02_gitee/rootfs.ext4.img' and probing guessed raw. automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. specify the 'raw' format explicitly to remove the restrictions.pulseaudio: set_sink_input_volume() failedpulseaudio: reason: invalid argumentpulseaudio: set_sink_input_mute() failedpulseaudio: reason: invalid argumentbooting linux on physical cpu 0x0linux version 5.4.0+ (damon@ubuntu) (gcc version 9.2.1 20191025 (gnu toolchain for the a-profile architecture 9.2-2019.12 (arm-9.10))) #1 smp sat jan 14 15:12:10 cst 2023cpu: armv7 processor [410fc090] revision 0 (armv7), cr=10c5387dcpu: pipt / vipt nonaliasing data cache, vipt nonaliasing instruction cacheof: fdt: machine model: v2p-ca9memory policy: data cache writebackreserved memory: created dma memory pool at 0x4c000000, size 8 mibof: reserved mem: initialized node vram@4c000000, compatible id shared-dma-poolcma: reserved 16 mib at 0x7f000000cpu: all cpu(s) started in svc mode.percpu: embedded 19 pages/cpu s45516 r8192 d24116 u77824built 1 zonelists, mobility grouping on. total pages: 130048kernel command line: root=/dev/mmcblk0 rw console=ttyama0printk: log_buf_len individual max cpu contribution: 4096 bytesprintk: log_buf_len total cpu_extra contributions: 12288 bytesprintk: log_buf_len min size: 16384 bytesprintk: log_buf_len: 32768 bytesprintk: early log buf free: 14808(90%)dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)mem auto-init: stack:off, heap alloc:off, heap free:offmemory: 492108k/524288k available (7168k kernel code, 425k rwdata, 1728k rodata, 1024k init, 155k bss, 15796k reserved, 16384k cma-reserved)slub: hwalign=64, order=0-3, minobjects=0, cpus=4, nodes=1rcu: hierarchical rcu implementation.rcu: rcu event tracing is enabled.rcu: rcu restricting cpus from nr_cpus=8 to nr_cpu_ids=4.rcu: rcu calculated value of scheduler-enlistment delay is 10 jiffies.rcu: adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4nr_irqs: 16, nr_irqs: 16, preallocated irqs: 16gic cpu mask not found - kernel will fail to boot.gic cpu mask not found - kernel will fail to boot.l2c: platform modifies aux control register: 0x02020000 - > 0x02420000l2c: dt/platform modifies aux control register: 0x02020000 - > 0x02420000l2c-310 enabling early bresp for cortex-a9l2c-310 full line of zeros enabled for cortex-a9l2c-310 dynamic clock gating disabled, standby mode disabledl2c-310 cache controller enabled, 8 ways, 128 kbl2c-310: cache_id 0x410000c8, aux_ctrl 0x46420001random: get_random_bytes called from start_kernel+0x310/0x4bc with crng_init=0sched_clock: 32 bits at 24mhz, resolution 41ns, wraps every 89478484971nsclocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 nsfailed to initialize '/smb@4000000/motherboard/iofpga@7,00000000/timer@12000': -22smp_twd: clock not found -2console: colour dummy device 80x30calibrating local timer... 97.07mhz.calibrating delay loop... 1179.64 bogomips (lpj=5898240)pid_max: default: 32768 minimum: 301mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)cpu: testing write buffer coherency: okcpu0: spectre v2: using bpiall workaroundcpu0: thread -1, cpu 0, socket 0, mpidr 80000000setting up static identity map for 0x60100000 - 0x60100060rcu: hierarchical srcu implementation.smp: bringing up secondary cpus ...smp: brought up 1 node, 1 cpusmp: total of 1 processors activated (1179.64 bogomips).cpu: all cpu(s) started in svc mode.devtmpfs: initializedvfp support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 0clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 nsfutex hash table entries: 1024 (order: 4, 65536 bytes, linear)net: registered protocol family 16dma: preallocated 256 kib pool for atomic coherent allocationscpuidle: using governor ladderhw-breakpoint: debug architecture 0x4 unsupported.serial: amba pl011 uart driver10009000.uart: ttyama0 at mmio 0x10009000 (irq = 29, base_baud = 0) is a pl011 rev1printk: console [ttyama0] enabled1000a000.uart: ttyama1 at mmio 0x1000a000 (irq = 30, base_baud = 0) is a pl011 rev11000b000.uart: ttyama2 at mmio 0x1000b000 (irq = 31, base_baud = 0) is a pl011 rev11000c000.uart: ttyama3 at mmio 0x1000c000 (irq = 32, base_baud = 0) is a pl011 rev1of: amba_device_add() failed (-19) for /smb@4000000/motherboard/iofpga@7,00000000/wdt@f000of: amba_device_add() failed (-19) for /memory-controller@100e0000of: amba_device_add() failed (-19) for /memory-controller@100e1000of: amba_device_add() failed (-19) for /watchdog@100e5000irq: type mismatch, failed to map hwirq-75 for interrupt-controller@1e001000!scsi subsystem initializedusbcore: registered new interface driver usbfsusbcore: registered new interface driver hubusbcore: registered new device driver usbadvanced linux sound architecture driver initialized.clocksource: switched to clocksource arm,sp804net: registered protocol family 2tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes, linear)tcp established hash table entries: 4096 (order: 2, 16384 bytes, linear)tcp bind hash table entries: 4096 (order: 3, 32768 bytes, linear)tcp: hash tables configured (established 4096 bind 4096)udp hash table entries: 256 (order: 1, 8192 bytes, linear)udp-lite hash table entries: 256 (order: 1, 8192 bytes, linear)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 armv7_cortex_a9 pmu driver, 1 counters availableworkingset: timestamp_bits=30 max_order=17 bucket_order=0squashfs: version 4.0 (2009/01/31) phillip lougherjffs2: version 2.2. (nand) © 2001-2006 red hat, inc.9p: installing v9fs 9p2000 file system supportio scheduler mq-deadline registeredio scheduler kyber registereddrm-clcd-pl111 1001f000.clcd: assigned reserved memory node vram@4c000000drm-clcd-pl111 1001f000.clcd: using device-specific reserved memorydrm-clcd-pl111 1001f000.clcd: initializing versatile express pl111drm-clcd-pl111 1001f000.clcd: core tile graphics presentdrm-clcd-pl111 1001f000.clcd: this device will be deactivatederror: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcdphysmap-flash 40000000.flash: physmap platform flash device: [mem 0x40000000-0x43ffffff]40000000.flash: found 2 x16 devices at 0x0 in 32-bit bank. manufacturer id 0x000000 chip id 0x000000intel/sharp extended query table at 0x0031using buffer write methodphysmap-flash 40000000.flash: physmap platform flash device: [mem 0x44000000-0x47ffffff]40000000.flash: found 2 x16 devices at 0x0 in 32-bit bank. manufacturer id 0x000000 chip id 0x000000intel/sharp extended query table at 0x0031using buffer write methodconcatenating mtd devices:(0): 40000000.flash(1): 40000000.flashinto device 40000000.flashphysmap-flash 48000000.psram: physmap platform flash device: [mem 0x48000000-0x49ffffff]libphy: fixed mdio bus: probedlibphy: smsc911x-mdio: probedsmsc911x 4e000000.ethernet eth0: mac address: 52:54:00:12:34:56isp1760 4f000000.usb: bus width: 32, oc: digitalisp1760 4f000000.usb: nxp isp1760 usb host controllerisp1760 4f000000.usb: new usb bus registered, assigned bus number 1isp1760 4f000000.usb: scratch test failed.isp1760 4f000000.usb: can't setup: -19isp1760 4f000000.usb: usb bus 1 deregisteredusbcore: registered new interface driver usb-storagertc-pl031 10017000.rtc: registered as rtc0mmci-pl18x 10005000.mmci: got cd gpiommci-pl18x 10005000.mmci: got wp gpiommci-pl18x 10005000.mmci: mmc0: pl181 manf 41 rev0 at 0x10005000 irq 25,26 (pio)ledtrig-cpu: registered to indicate activity on cpususbcore: registered new interface driver usbhidusbhid: usb hid core driveraaci-pl041 10004000.aaci: arm ac'97 interface pl041 rev0 at 0x10004000, irq 24aaci-pl041 10004000.aaci: fifo 512 entriesoprofile: using arm/armv7-ca9net: registered protocol family 179pnet: installing 9p2000 supportregistering swp/swpb emulation handlererror: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcderror: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcdinput: at raw set 2 keyboard as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10006000.kmi/serio0/input/input0mmc0: new sd card at address 4567error: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcdmmcblk0: mmc0:4567 qemu! 500 miberror: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcdrtc-pl031 10017000.rtc: setting system clock to 2023-01-14t15:23:16 utc (1673709796)alsa device list: #0: arm ac'97 interface pl041 rev0 at 0x10004000, irq 24input: imexps/2 generic explorer mouse as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2error: driver 'vexpress-muxfpga' is already registered, aborting...drm-clcd-pl111 10020000.clcd: initializing versatile express pl111drm-clcd-pl111 10020000.clcd: dvi muxed to daughterboard 1 (core tile) clcdrandom: fast init doneext4-fs (mmcblk0): recovery completeext4-fs (mmcblk0): mounted filesystem with ordered data mode. opts: (null)ext4 filesystem being mounted at /root supports timestamps until 2038 (0x7fffffff)vfs: mounted root (ext4 filesystem) on device 179:0.freeing unused kernel memory: 1024krun /sbin/init as init processrandom: crng init donecan't run '/etc/init.d/rcs': no such file or directoryplease press enter to activate this console.please press enter to activate this console.please press enter to activate this console.please press enter to activate this console./ #我们完成了linux源码的编译和启动,但是此时我们还没有看一行代码!
接下来,我们就开始阅读第一行代码并分析kernel的启动流程。
运动机器人何时才能拥有运动脑,不再是“人工智障”
自制示波器探头
Ice-Lake-U 处理器型号比 Ice Lake-U 芯片强 31%左右?
医疗垃圾智能化回收方案
led不同封装方法造成的影响
Linux内核的编译和运行
金升阳科技发布元器件100%国产化的DC/DC电源模块产品
蜂窝物联茶叶种植智能管理系统
ADI产品线
不同vlan间的通信简单配置的三种方式解析
智慧路灯杆系统的功能以及它的组成结构是怎样的
显示应用市场回暖,封装或将缺货涨价
波导隔离器是什么,它的主要作用是什么
SO2传感器在工业废气源监测中的应用介绍
DRAM的价格下跌和需求疲软 或将持续到2019年第三季度
一分钟告诉你!智能家居安防系统中有哪五大优势?
锡膏保存期限是多久?
中国国家电网打破了输电电压、距离和功率的世界纪录
Quartz中编码中用到的几个对象
意法半导体在深圳举办首届工业峰会