一、【linux启动】嵌入式Linux系统启动过程分析
一、概述
嵌入式linux系统启动过程一般包含以下几个过程:
- 上电
- 执行IROM(芯片内部只读存储器)中固化的代码。
- 执行uboot
- 加载内核到内存,启动内核。
- 挂载根文件系统rootfs
- 执行其中的脚本和应用程序。
二、linux操作系统的几个组成部分介绍
1、uboot介绍
(1)概述
- 是一个通用的bootloader
- Boot:完成硬件的初始化
-
Loader:加载操作系统内核,并启动内核.
- uboot支持多种处理器架构:ARM、PowerPC 、X86 、 Mips等等。
- 支持加载启动多种操作系统:linux、wince、VXworks等
- uboot的源码下载地址:https://ftp.denx.de/pub/u-boot/
(2)作用
- CPU的初始化(芯片级)主要采用ARM汇编语言,包含初始化缓存、MMC、Watchdog、终端、clock等。
- 板级初始化(采用C语言编写):主要初始化串口、网卡、USB、LCD等设备.
-
为操作系统的启动准备参数,加载操作系统镜像到内存,并启动.
(3)u-boot的开机打印信息分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | U-Boot 2014.07 (Apr 10 2021 - 02:16:01)---U-boot版本号 //时钟系统中各个总线上的时钟频率 PLL : [0] = 800000000, [1] = 800000000, [2] = 780000000, [3] = 800000000 (0) PLL1: CPU FCLK = 800000000, HCLK = 200000000 (G0) (7) PLL1: CPU FCLK = 800000000, HCLK = 200000000 (G1) (2) PLL3: MEM FCLK = 800000000, DCLK = 800000000, BCLK = 400000000, PCLK = 200000000 (1) PLL0: BUS BCLK = 400000000, PCLK = 200000000 (8) PLL0: CCI4 BCLK = 400000000, PCLK = 200000000 (3) PLL0: G3D BCLK = 400000000 (4) PLL0: CODA BCLK = 400000000, PCLK = 200000000 (5) PLL0: DISP BCLK = 400000000, PCLK = 200000000 (6) PLL0: HDMI PCLK = 133333333 I2C: ready DRAM: 1 GiB------------内存1GB Heap = 0x44000000~0x46000000 Code = 0x43c00000~0x43c83e48 GLD = 0x43bffeb8 GLBD = 0x43bffe68 SP = 0x43bffe68,0x43bffe48(CURR) PC = 0x43c06640 TAGS = 0x40000100 PAGE = 0x43c90000~0x43c9c000 MACH = [4330] VER = 0 BOARD= [GEC6818] MMC: NXP DWMMC: 0, NXP DWMMC: 1, NXP DWMMC: 2 In: serial Out: serial Err: serial ## DCDC_MODE(0x80): DCDC1[PFM], DCDC2[PFM], DCDC3[PFM], DCDC4[PWM], DCDC5[PWM] ## STATUS(0x00) : 0xe4 0x10 ## IRQ(0x48) : 0x00 0x00 0x00 0x00 0x00 ## CHG_TYPE : ADP ## BAT_VOL : 0mV ## BAT_CAP : 100% DONE: Logo bmp 300 by 300 (3bpp), len=270056 DRAW: 0x47000000 -> 0x46000000 DONE: Logo bmp 300 by 300 (3bpp), len=270056 DRAW: 0x47000000 -> 0x46000000 RGB: display.0 MIPI: display.0 DSIM_ESCMODE 1 : 0xc0 DSIM_STATUS : 0x10010f MIPI clk: 420MHz DSIM_ESCMODE 2 : 0x0 DSIM_STATUS : 0x10010f ## Skip BAT Animation. ## IRQ(0x48) : 0x00 0x00 0x00 0x00 0x00 ## chg_type : ADP ## battery_vol : 0mV ## battery_cap : 100% ## Booting Card did not respond to voltage select! Net: GEC6818 mac init... dwmac.c0060000 Hit any key to stop autoboot: 0---倒计时结束加载启动内核,倒计时结束前按下键盘上的任意按键,进入U-BOOT命令行 |
(4)uboot的命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | => help // 在uboot下执行help看uboot下的帮助文档 ? - alias for 'help' base - print or set address offset bdinfo - print Board Info structure blkcache - block cache diagnostics and control boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootefi - Boots an EFI payload from memory bootelf - Boot from an ELF image in memory bootm - boot application image from memory bootp - boot image via network using BOOTP /TFTP protocol bootvx - Boot vxWorks from an ELF image bootz - boot Linux zImage image from memory cmp - memory compare coninfo - print console devices and information cp - memory copy crc32 - checksum calculation dhcp - boot image via network using DHCP /TFTP protocol dm - Driver model low level access echo - echo args to console editenv - edit environment variable env - environment handling commands erase - erase FLASH memory exit - exit script ext2load - load binary file from a Ext2 filesystem ext2ls - list files in a directory (default /) ext4load - load binary file from a Ext4 filesystem ext4ls - list files in a directory (default /) ext4size - determine a file 's size false - do nothing, unsuccessfully fatinfo - print information about filesystem fatload - load binary file from a dos filesystem fatls - list files in a directory (default /) fatmkdir - create a directory fatrm - delete a file fatsize - determine a file 's size fatwrite - write file into a dos filesystem fdt - flattened device tree utility commands flinfo - print FLASH memory information fstype - Look up a filesystem type go - start application at address 'addr' gpio - query and control gpio pins gpt - GUID Partition Table help - print command description /usage iminfo - print header information for application image imxtract - extract a part of a multi-image itest - return true /false on integer compare ln - Create a symbolic link load - load binary file from a filesystem loadb - load binary file over serial line (kermit mode) loads - load S-Record file over serial line loadx - load binary file over serial line (xmodem mode) loady - load binary file over serial line (ymodem mode) loop - infinite loop on address range ls - list files in a directory (default /) md - memory display mdio - MDIO utility commands mii - MII utility commands mm - memory modify (auto-incrementing address) mmc - MMC sub system mmcinfo - display MMC info mtd - MTD utils mw - memory write (fill) nfs - boot image via network using NFS protocol nm - memory modify (constant address) part - disk partition related commands ping - send ICMP ECHO_REQUEST to network host printenv - print environment variables protect - enable or disable FLASH write protection pxe - commands to get and boot from pxe files random - fill memory with random pattern reset - Perform RESET of the CPU run - run commands in an environment variable save - save file to a filesystem saveenv - save environment variables to persistent storage setenv - set environment variables setexpr - set environment variable as the result of eval expression sf - SPI flash sub-system showvar - print local hushshell variables size - determine a file 's size sleep - delay execution for some time source - run script from memory sysboot - command to get and boot from syslinux files test - minimal test like /bin/sh tftpboot - boot image via network using TFTP protocol true - do nothing, successfully usb - USB sub-system usbboot - boot from USB device version - print monitor, compiler and linker version |
- bdinfo:打印出开发板的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | GEC6818 # bdinfo arch_number = 0x000010EA-------开发板的编号,要与内核源码中开发板编号一致 boot_params = 0x40000100-------启动内核所需参数在内存的0x40000100处 DRAM bank = 0x00000000 -> start = 0x40000000-----------内存的起始地址,结束地址0x7fffffff -> size = 0x40000000-----------内存的大小 1GB eth0name = dwmac.c0060000---网卡的名字 ethaddr = 00:e2:1c:ba:e8:60 --网卡的MAC地址 current eth = dwmac.c0060000 ip_addr = 192.168.51.5----------U-BOOT设置的网卡IP baudrate = 115200 bps-----------串口的波特率 TLB addr = 0x7FFF0000 relocaddr = 0x46000000 reloc off = 0x00000000 irq_sp = 0x7DF6BF00 sp start = 0x43BFFE6 |
- 启动内核的命令
1 2 3 4 | boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootm - boot application image from memory bootp - boot image via network using BOOTP /TFTP protocol |
- printenv:打印环境变量
1 2 3 4 | GEC6818 # printenv baudrate=115200 bootargs=lcd=at070tn92 tp=gslx680-linux root= /dev/mmcblk0p2 rw rootfstype=ext4 bootcmd=ext4load mmc 2:1 0x48000000 uImage;bootm 0x48000000 |
两个重要的环境变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | bootargs启动参数:告诉内核一些重要启动信息 lcd=at070tn92-------------LCD屏驱动芯片的型号 tp=gslx680-linux-----------触摸屏的型号 root= /dev/mmcblk0p2---- 根文件系统在emmc的第2个分区 rw rootfstype=ext4--------根文件系统可读可写,类型是ext4 bootcmd--------------------启动命令环境变量,告诉U-boot一些信息 bootcmd=ext4load mmc 2:1 0x48000000 uImage;bootm 0x48000000 以ext4格式把内核镜像uImage从emmc的第1分区加载到内存的0x48000000处,然后去到内存0x48000000处,启动内核 bootdelay=3---------------倒计时3S bootfile=uImage ethact=dwmac.c0060000 ethaddr=00:e2:1c:ba:e8:60 ethprime=RTL8211------网卡芯片的型号 gatewayip=192.168.51.1-----------------默认网关 ipaddr=192.168.51.5---------------------开发板IP netmask=255.255.255.0----------------子网掩码 qtcrc=-1489582083 serverip=192.168.51.2-------------------服务器IP stderr=serial stdin=serial stdout=serial |
- setenv :设置(修改)环境变量的值
1 2 3 4 | GEC6818 # setenv bootdelay 5 -----------把环境变量bootdelay的值修改为5 GEC6818 # saveenv-----------------------------保存环境变量的修改 Saving Environment to MMC... Writing to MMC(2)... doner |
- reset:重启主板
- go:去到内存某个地址执行程序。
1 2 | GEC6818 # go 0x40000000------------去到内存0x40000000处,执行程序 ## Starting application at 0x40000000 .. |
- ping :测试网络连通性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Environment size: 843 /32764 bytes GEC6818 # setenv ipaddr 192.168.1.21 -----设置开发板自己的IP GEC6818 # setenv netmask 255.255.255.0 GEC6818 # setenv gatewayip 192.168.1.1 GEC6818 # setenv serverip 192.168.1.20 GEC6818 # saveenv Saving Environment to MMC... Writing to MMC(2)... done Writing to MMC(2)... done GEC6818 # ping 192.168.1.20 Speed: 100, full duplex Using dwmac.c0060000 device host 192.168.1.20 is alive----------------网络连通 |
- tftp:运行tftpd32.exe,相当于在windows下搭建了tftp服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | GEC6818 # setenv serverip 192.168.1.20---在开发板U-BOOT中设置服务器IP为windows IP GEC6818 # save Saving Environment to MMC... Writing to MMC(2)... done GEC6818 # tftp 0x40000000 tftpd32.ini-----从tftp服务器上下载一个名字为tftpd32.ini的文件到内存0x40000000处 Speed: 100, full duplex Using dwmac.c0060000 device TFTP from server 192.168.1.20; our IP address is 192.168.1.21 Filename 'tftpd32.ini' . Load address: 0x40000000 Loading: # 7.8 KiB /s done Bytes transferred = 530 (212 hex) |
2、内核
(1)内核的作用
-
进程调度与进程通信
- 内存管理
- 文件管理
- 设备驱动管理
- 网络通信---TCP/IP
kernel源码下载地址:https://mirrors.edge.kernel.org/pub/linux/kernel/
(2)linux内核启动时的输出信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | ## Booting kernel from Legacy Image at 48000000 ... Image Name: Linux-3.4.39-gec -----------内核版本 3 主版本号 4 次版本号 偶数:稳定版 奇数:开发版 39 修订版本号 Gec 扩展版本号 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 5575624 Bytes = 5.3 MiB Load Address: 40008000 Entry Point: 40008000 Verifying Checksum ... OK Loading Kernel Image ... OK Starting kernel ... --------------------开始启动内核 [ 0.000000] Booting Linux on physical CPU 0 -------------在CPU0 上启动Linux [ 0.000000] Memory: 1024MB = 1024MB total [ 0.000000] Memory: 810728k /810728k available, 237848k reserved, 272384K highmem 虚拟内存的划分 [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) [ 0.000000] vmalloc : 0xef800000 - 0xfee00000 ( 246 MB) [ 0.000000] lowmem : 0xc0000000 - 0xef600000 ( 758 MB) [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB) [ 0.000000] .text : 0xc0008000 - 0xc0a65214 (10613 kB) [ 0.000000] .init : 0xc0a66000 - 0xc0aa3100 ( 245 kB) [ 0.000000] .data : 0xc0aa4000 - 0xc0b3ec88 ( 620 kB) [ 0.000000] .bss : 0xc0b3ecac - 0xc0d203c8 (1926 kB) 外设的初始化 [ 0.173000] usbcore: registered new interface driver usbfs [ 0.174000] usbcore: registered new interface driver hub [ 0.174000] usbcore: registered new device driver usb [ 0.174000] i2c-gpio i2c-gpio.0: using pins 99 (SDA) and 98 (SCL) [ 0.175000] i2c-gpio i2c-gpio.3: using pins 80 (SDA) and 79 (SCL) [ 0.176000] s3c-i2c s3c2440-i2c.1: i2c-1: S3C I2C adapter [ 0.176000] s3c-i2c s3c2440-i2c.1: slave address 0x10 [ 0.176000] s3c-i2c s3c2440-i2c.1: bus frequency set to 97 KHz [ 0.178000] s3c-i2c s3c2440-i2c.2: i2c-2: S3C I2C adapter [ 0.178000] s3c-i2c s3c2440-i2c.2: slave address 0x10 [ 0.178000] s3c-i2c s3c2440-i2c.2: bus frequency set to 97 KHz 网络协议 [ 0.331000] NET: Registered protocol family 2 [ 0.331000] IP route cache hash table entries: 32768 (order: 5, 131072 bytes) [ 0.332000] TCP established hash table entries: 131072 (order: 8, 1048576 bytes) [ 0.334000] TCP bind hash table entries: 65536 (order: 8, 1572864 bytes) [ 0.336000] TCP: Hash tables configured (established 131072 bind 65536) [ 0.336000] TCP: reno registered [ 0.336000] UDP hash table entries: 512 (order: 3, 32768 bytes) [ 0.336000] UDP-Lite hash table entries: 512 (order: 3, 32768 bytes) [ 0.337000] NET: Registered protocol family 1 [ 0.337000] RPC: Registered named UNIX socket transport module. [ 0.337000] RPC: Registered udp transport module. [ 0.337000] RPC: Registered tcp transport module. [ 0.337000] RPC: Registered tcp NFSv4.1 backchannel transport module. 挂载根文件系统 [ 5.996000] VFS: Mounted root (ext4 filesystem) on device 179:2. [ 6.003000] devtmpfs: mounted [ 6.005000] Freeing init memory: 244K [ 6.009000] Write protecting the kernel text section c0008000 - c0a2f000 [ 6.016000] rodata_test: attempting to write to read -only section: [ 6.022000] write to read -only section trapped, success [ 6.166000] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered [ 6.539000] eth0: device MAC address 6e:3a:61:c8:01:f4 [ 6.546000] stmmac_open: failed PTP initialization 可以用 mount 命令查看所有的挂载信息和文件系统格式 [root@GEC6818 /] #mount rootfs on / type rootfs (rw) /dev/root on / type ext4 (rw, sync ,relatime,data=ordered) devtmpfs on /dev type devtmpfs (rw,relatime,size=405364k,nr_inodes=101341,mode=755) proc on /proc type proc (rw,relatime) devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620) tmpfs on /dev/shm type tmpfs (rw,relatime,mode=777) tmpfs on /tmp type tmpfs (rw,relatime) tmpfs on /run type tmpfs (rw,nosuid,nodev,relatime,mode=755) sysfs on /sys type sysfs (rw,relatime) |
3、根文件系统
(1)概述
根文件系统是一个“包”,里面包含很多内容
- shell命令和可执行程序:/bin /sbin /usr/bin
- 设备文件: /dev
- 配置文件或脚本/etc 例如:/etc/profile就是一个脚本
- 库文件(动态库) *.so /lib /usr/lib
- /proc 该目录下的文件,存放了系统运行的实时状态信息
1 2 3 4 5 6 7 8 9 | [root@GEC6818 /] #ls /proc/ 1 22 49 buddyinfo meminfo 10 23 5 bus misc 100 24 50 cgroups modules 101 25 51 cmdline mounts 102 26 52 config.gz net 103 27 53 consoles pagetypeinfo 104 28 6 cpu partitions 105 29 7 cpuinfo sched_debug |
以数字命名的目录文件,数字是进程的PID,目录下文件中存储的是进程的状态信息
- /sys 该目录下的文件存储了驱动相关信息
- /mnt ------挂载点
- /usr-----用户程序或库文件
- /opt ------第三方的大软件
- /val--------------系统日志目录
根文件系统挂载后:
- 执行脚本/etc/init.d/rcS
- 执行/etc/profile
- 装载驱动模块
- 执行iot应用程序。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)