【linux kernel】start_kernel函数详解系列之开篇

start_kernel函数详解系列之开篇

一、背景

linux 内核启动过程中,start_kernel()函数是分析Linux内核的切入点。小生想着对start_kernel函数体中一连串的函数调用过程进行分析和学习。也计划将这些输出、总结成相应文档和笔记。本篇文章作为《start_kernel详解系列》的开篇笔记。于是便有了本篇文章。

【实验环境】


  • linux内核版本:4.1.15
  • 开发环境:ubuntu 18.4
  • 运行平台:nxp - imx6ull

二、start_kernel函数打印信息概览

在本文中,小生将linux内核向终端打印出的消息作为分析概览,并使用printk()函数在源码相应位置打印出对应的标记信息。如下所示:

【start_kernel打印出的信息】
(注,信息有点长)

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 4.1.15 (iriczhao@iriczhao) (gcc version 5.5.0 (Linaro GCC 5.5-2017.10) ) #4 SMP PREEMPT Sat Feb 26 11:48:48 CST 2022
CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine model: Freescale i.MX6 ULL 14x14 EVK Board
Reserved memory: created CMA memory pool at 0x98000000, size 128 MiB
Reserved memory: initialized node linux,cma, compatible id shared-dma-pool
Memory policy: Data cache writealloc
PERCPU: Embedded 12 pages/cpu @97b90000 s16768 r8192 d24192 u49152
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 130048
Kernel command line: console=tty1 console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.1.30:/home/iriczhao/linux_dev_server/nfs/rootfs ip=192.168.1.9:192.168.1.30:192.168.1.1:255.255.255.0::eth0:off
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 377784K/524288K available (6927K kernel code, 322K rwdata, 2360K rodata, 396K init, 424K bss, 15432K reserved, 131072K cma-reserved, 0K highmem)
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0xa0800000 - 0xff000000   (1512 MB)
    lowmem  : 0x80000000 - 0xa0000000   ( 512 MB)
    pkmap   : 0x7fe00000 - 0x80000000   (   2 MB)
    modules : 0x7f000000 - 0x7fe00000   (  14 MB)
      .text : 0x80008000 - 0x8091a134   (9289 kB)
      .init : 0x8091b000 - 0x8097e000   ( 396 kB)
      .data : 0x8097e000 - 0x809ce900   ( 323 kB)
       .bss : 0x809d1000 - 0x80a3b2d4   ( 425 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptible hierarchical RCU implementation.
	Additional per-CPU info printed with stalls.
	RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=1.
RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
NR_IRQS:16 nr_irqs:16 16
mxc_clocksource_init 3000000
Switching to timer-based delay loop, resolution 333ns
sched_clock: 32 bits at 3000kHz, resolution 333ns, wraps every 715827882841ns
clocksource mxc_timer1: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 637086815595 ns
Console: colour dummy device 80x30
console [tty1] enabled
Calibrating delay loop (skipped), value calculated using timer frequency.. 6.00 BogoMIPS (lpj=30000)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
CPU: Testing write buffer coherency: ok

[1]===================================================
【rest_init()】
[2]===================================================

/cpus/cpu@0 missing clock-frequency property
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000

[3]===================================================
Setting up static identity map for 0x80008280 - 0x800082f0
Brought up 1 CPUs
SMP: Total of 1 processors activated (6.00 BogoMIPS).
CPU: All CPU(s) started in SVC mode.

[4]===================================================
devtmpfs: initialized
device-tree: Duplicate name in lcdif@021c8000, renamed to "display#1"
VFP support v0.3: implementor 41 architecture 2 part 30 variant 7 rev 5
clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
cpuidle: using governor menu
hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers.
hw-breakpoint: maximum watchpoint size is 8 bytes.
imx6ul-pinctrl 20e0000.iomuxc: initialized IMX pinctrl driver
imx6ul-pinctrl 2290000.iomuxc-snvs: initialized IMX pinctrl driver
mxs-dma 1804000.dma-apbh: initialized
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
i2c i2c-0: IMX I2C adapter registered
i2c i2c-0: can't use DMA
i2c i2c-1: IMX I2C adapter registered
i2c i2c-1: can't use DMA
Linux video capture interface: v2.00
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
Advanced Linux Sound Architecture Driver Initialized.
Switched to clocksource mxc_timer1
NET: Registered protocol family 2
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
imx rpmsg driver is registered.
Bus freq driver module loaded
futex hash table entries: 256 (order: 2, 16384 bytes)
VFS: Disk quotas dquot_6.6.0
VFS: Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
NFS: Registering the id_resolver key type
Key type id_resolver registered
Key type id_legacy registered
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
fuse init (API version 7.23)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
imx-weim 21b8000.weim: Driver registered.
backlight supply power not found, using dummy regulator
21c8000.lcdif supply lcd not found, using dummy regulator
mxsfb 21c8000.lcdif: failed to find mxc display driver 
Console: switching to colour frame buffer device 128x37
mxsfb 21c8000.lcdif: initialized
imx-sdma 20ec000.sdma: no event needs to be remapped
imx-sdma 20ec000.sdma: loaded firmware 3.3
imx-sdma 20ec000.sdma: initialized
2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 19, base_baud = 5000000) is a IMX
console [ttymxc0] enabled
21ec000.serial: ttymxc2 at MMIO 0x21ec000 (irq = 233, base_baud = 5000000) is a IMX
imx sema4 driver is registered.
[drm] Initialized drm 1.1.0 20060810
[drm] Initialized vivante 1.0.0 20120216 on minor 0
brd: module loaded
loop: module loaded
fsl-quadspi 21e0000.qspi: unrecognized JEDEC id bytes: ff, ff, ff
fsl-quadspi 21e0000.qspi: Freescale QuadSPI probe failed
spi_imx 2010000.ecspi: probed
20b4000.ethernet supply phy not found, using dummy regulator
pps pps0: new PPS source ptp0
libphy: fec_enet_mii_bus: probed
fec 20b4000.ethernet eth0: registered PHC device 0
2188000.ethernet supply phy not found, using dummy regulator
pps pps1: new PPS source ptp1
fec 2188000.ethernet eth1: registered PHC device 1
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-mxc: Freescale On-Chip EHCI Host driver
usbcore: registered new interface driver usb-storage
2184800.usbmisc supply vbus-wakeup not found, using dummy regulator
2184000.usb supply vbus not found, using dummy regulator
ci_hdrc ci_hdrc.0: EHCI Host Controller
ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
2184200.usb supply vbus not found, using dummy regulator
ci_hdrc ci_hdrc.1: EHCI Host Controller
ci_hdrc ci_hdrc.1: new USB bus registered, assigned bus number 2
ci_hdrc ci_hdrc.1: USB 2.0 started, EHCI 1.00
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 1 port detected
Mass Storage Function, version: 2009/09/11
LUN: removable file: (no medium)
no file given for LUN0
g_mass_storage ci_hdrc.0: failed to start g_mass_storage: -22
mousedev: PS/2 mouse device common for all mice
input: 20cc000.snvs:snvs-powerkey as /devices/platform/soc/2000000.aips-bus/20cc000.snvs/20cc000.snvs:snvs-powerkey/input/input0
snvs_rtc 20cc000.snvs:snvs-rtc-lp: rtc core: registered 20cc000.snvs:snvs-r as rtc0
i2c /dev entries driver
IR NEC protocol handler initialized
IR RC5(x/sz) protocol handler initialized
IR RC6 protocol handler initialized
IR JVC protocol handler initialized
IR Sony protocol handler initialized
IR SANYO protocol handler initialized
IR Sharp protocol handler initialized
IR MCE Keyboard/mouse protocol handler initialized
IR XMP protocol handler initialized
pxp-v4l2 pxp_v4l2: initialized
imx2-wdt 20bc000.wdog: use WDOG_B to reboot.
imx2-wdt 20bc000.wdog: timeout 60 sec (nowayout=0)
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
/soc/aips-bus@02100000/usdhc@02190000: voltage-ranges unspecified
sdhci-esdhc-imx 2190000.usdhc: Got CD GPIO
sdhci-esdhc-imx 2190000.usdhc: No vqmmc regulator found
mmc0: SDHCI controller on 2190000.usdhc [2190000.usdhc] using ADMA
usb 2-1: new high-speed USB device number 2 using ci_hdrc
/soc/aips-bus@02100000/usdhc@02194000: voltage-ranges unspecified
sdhci-esdhc-imx 2194000.usdhc: No vmmc regulator found
sdhci-esdhc-imx 2194000.usdhc: No vqmmc regulator found
mmc0: host does not support reading read-only switch, assuming write-enable
mmc1: SDHCI controller on 2194000.usdhc [2194000.usdhc] using ADMA
usbcore: registered new interface driver usbhid
mmc0: new high speed SDHC card at address aaaa
usbhid: USB HID core driver
mmcblk0: mmc0:aaaa SU04G 3.69 GiB 
NET: Registered protocol family 10
 mmcblk0:
hub 2-1:1.0: USB hub found
sit: IPv6 over IPv4 tunneling driver
hub 2-1:1.0: 4 ports detected
NET: Registered protocol family 17
Key type dns_resolver registered
Registering SWP/SWPB emulation handler
input: gpio_keys@0 as /devices/platform/gpio_keys@0/input/input1
snvs_rtc 20cc000.snvs:snvs-rtc-lp: setting system clock to 1970-01-01 00:16:04 UTC (964)
mmc1: MAN_BKOPS_EN bit is not set
mmc1: new HS200 MMC card at address 0001
mmcblk1: mmc1:0001 8GTF4R 7.28 GiB 
mmcblk1boot0: mmc1:0001 8GTF4R partition 1 4.00 MiB
mmcblk1boot1: mmc1:0001 8GTF4R partition 2 4.00 MiB
mmcblk1rpmb: mmc1:0001 8GTF4R partition 3 512 KiB
 mmcblk1: p1 p2
fec 20b4000.ethernet eth0: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=20b4000.ethernet:01, irq=-1)
IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
fec 20b4000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
IP-Config: Complete:
     device=eth0, hwaddr=00:04:9f:04:d2:32, ipaddr=192.168.1.9, mask=255.255.255.0, gw=192.168.1.1
     host=192.168.1.9, domain=, nis-domain=(none)
     bootserver=192.168.1.30, rootserver=192.168.1.30, rootpath=
can-3v3: disabling
ALSA device list:
  No soundcards found.

[5]===================================================

[6]===================================================
VFS: Mounted root (nfs filesystem) on device 0:15.
devtmpfs: mounted

[7]===================================================
Freeing unused kernel memory: 396K (8091b000 - 8097e000)

三、linux启动早期打印的信息

在4.1.15版本的linux内核中,start_kernel()函数最后会调用rest_init()执行剩下的启动操作。那么就在该函数上方使用printk()打印出第一条信息:

asmlinkage __visible void __init start_kernel(void)
{
	char *command_line;
	char *after_dashes;

/*  中间省略大量函数调用*/

	printk("\r\n[1]===================================================\r\n");

	rest_init();
}

从打印出的信息来开,linux启动后直到rest_init()函数调用之前打印出的信息位于【1-45】行。

四、smp_prepare_cpus()打印出的信息

以下打印信息:

[2]===================================================

/cpus/cpu@0 missing clock-frequency property
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000

[3]===================================================

kernel_init_freeable()函数中:

	printk("\r\n[2]===================================================\r\n");

	smp_prepare_cpus(setup_max_cpus);

	printk("\r\n[3]===================================================\r\n");
五、do_basic_setu()打印出的信息

kernel_init_freeable()函数中:

	printk("\r\n[4]===================================================\r\n");

	do_basic_setup();

	printk("\r\n[5]===================================================\r\n");

在4和5行之间的printk打印出的信息非常多,可以说占用了linux输出的大部分信息,这些信息都由do_basic_setup()函数实现。可见该函数在linux启动过程较为重要。

六、prepare_namespace()打印出的信息

kernel_init_freeable()函数中:

printk("\r\n[6]===================================================\r\n");
prepare_namespace();
printk("\r\n[7]===================================================\r\n");

在6和7行之间的printk打印出的信息如下:

[6]===================================================
VFS: Mounted root (nfs filesystem) on device 0:15.
devtmpfs: mounted

[7]===================================================

从打印出的信息来看,prepare_namespace()在linux内核启动过程中也比较重要,该函数实现linux根文件系统的挂载和处理。

七、释放内核没使用的内存

最后一条打印信息:

Freeing unused kernel memory: 396K (8091b000 - 8097e000)

在linux启动的后面阶段,将释放掉没有使用的内核内存。

八、启动用户空间进程

​ 当根文件系统挂载完成后,linux将调用try_to_run_init_process()函数尝试启动用户空间进程。如果进程成功启动,就完成了内核空间向用户空间的转变过程。

九、总结

​ linux内核的启动主线较复杂,主线下的每一个模块分支展开的逻辑和关系网较庞大。在学习过程中,小生先从linux的形再到点逐一展开。注:不同linux版本以及不同内核配置情况,都会影响打印出的信息,但是主线中的关键几个地方是不会有太大改变,可以先对linux 内核启动过程有个形体上的概念和认识啦。


搜索关注【嵌入式小生】wx公众号获取更多精彩内容>>>>
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值