今天同事给讲了讲linux启动过程 粗略的一个分析 做个笔记
根据现在做的一些android项目分析linux系统启动过程 大体分成两个部分 compile startup 两部分相辅相成 紧密结合
1. compile
首先运行make menuconfig/config等congfig脚本 配置编译选项和系统配置选项
CONFIG_XXX_XXX=y 在内核有些作为配置选项 有些是编译进内核的模块(如插入移动硬盘 首先要将USB驱动加载到内核中 即make config时要选中编译USB模块 这样该模块就会在内核的vmlinux中了)
CONFIG_XXX_XXX=m 作为可加载的动态模块
还有一些数值和字符串 作为配置 也编译进内核 可以对应Autoconf.h文件查看各个选择的配置选项
编译后生成System.map和vmlinux(ELF) System.map文件包括所有编译进内核的函数和变量的地址 在后面startup中这个文件很重要 很多函数都需要在这个文件中找到对应的位置 还有一些编译进内核的模块的启动顺序即调用函数顺序 vmlinux文件时elf文件 内核中所有信息都可以在这里面找到 各个段可在vmlinux.lds.d中找到各段的顺序
2. startup
之前的过程网上都可以找到 直接从start_kernel()开始讲
在adb shell 中运行dmesg > /mnt/sdcard/filename 保存当前开机后的log 顺着这个线索我们explore in depth
2.1 start_kernel()
printk(KERN_NOTICE "%s", linux_banner);
Linux version 2.6.35.7-perf (dmsin@dmsin-desktop) (gcc version 4.4.3 (GCC) ) #3 PREEMPT Tue May 17 00:45:00 KST 2011
2.2 start_kernel()->setup_arch()
2.2.1 setup_arch()->setup_processor()
CPU: ARMv6-compatible processor [4117b365] revision 5 (ARMv6TEJ), cr=00c5387f
2.2.2 setup_arch()->setup_processor()->cacheid_init()
CPU: VIPT aliasing data cache, VIPT aliasing instruction cache
2.2.3 setup_arch()->setup_machine()
Machine: XXX Board
#define MACHINE_START(_type,_name) /
static const struct machine_desc __mach_desc_##_type /
__used /
__attribute__((__section__(".arch.info.init"))) = { /
.nr = MACH_TYPE_##_type, /
.name = _name,
#define MACHINE_END /
};
MACHINE_START(MSM7X27_SURF, "XXX Board")
#ifdef CONFIG_MSM_DEBUG_UART
.phys_io = MSM_DEBUG_UART_PHYS,
.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x2x_map_io,
.init_irq = msm7x2x_init_irq,
.init_machine = msm7x2x_init,
.timer = &msm_timer,
MACHINE_END
2.2.4 struct tag *tags = (struct tag *)&init_tags;
init_tags __initdata = {
{ tag_size(tag_core), ATAG_CORE },
{ 1, PAGE_SIZE, 0xff },
{ tag_size(tag_mem32), ATAG_MEM },
{ MEM_SIZE, PHYS_OFFSET },
{ 0, ATAG_NONE }
};
setup_arch()->parse_tags()->parse_tag()->parse_tag_core () && parse_tag_msm_partition ()
#define __tag __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) /
static struct tagtable __tagtable_##fn __tag = { tag, fn }
c002cf58 T __tagtable_begin
c002cf58 t __tagtable_parse_tag_cmdline
c002cf60 t __tagtable_parse_tag_revision
c002cf68 t __tagtable_parse_tag_serialnr
c002cf70 t __tagtable_parse_tag_ramdisk
c002cf78 t __tagtable_parse_tag_videotext
c002cf80 t __tagtable_parse_tag_mem32
c002cf88 t __tagtable_parse_tag_core
c002cf90 t __tagtable_parse_tag_initrd2
c002cf98 t __tagtable_parse_tag_initrd
c002cfa0 t __tagtable_parse_tag_msm_partition
c002cfa8 T __tagtable_end
Partition (from atag) mibib -- Offset:0 Size:6
Partition (from atag) qcsbl -- Offset:6 Size:2
Partition (from atag) oemsbl -- Offset:8 Size:3
Partition (from atag) amss -- Offset:b Size:64
Partition (from atag) efs2 -- Offset:6f Size:2f
Partition (from atag) nv_backup -- Offset:9e Size:14
Partition (from atag) fota -- Offset:b2 Size:18
Partition (from atag) arm11boot -- Offset:ca Size:8
2.2.5 setup_arch()->parse_early_param()->parse_early_options()->do_early_param()
Callisto H/W revision : 0x01
2.2.6 static struct mem_type mem_types[]
setup_arch()->paging_init()->build_mem_type_table()
Memory policy: ECC disabled, Data cache writeback
2.2.7 setup_arch()->paging_init()->bootmem_init()->bootmem_free_node()->free_area_init_node()->calculate_node_totalpages()
On node 0 totalpages: 86016
2.2.8 setup_arch()->paging_init()->bootmem_init()->bootmem_free_node()->free_area_init_node()
free_area_init_node: node 0, pgdat c06d5d98, node_mem_map c08dc000
2.2.9 setup_arch()->paging_init()->bootmem_init()->bootmem_free_node()->free_area_init_node()->free_area_init_core()
Normal zone: 672 pages used for memmap
Normal zone: 0 pages reserved
2.2.10 setup_arch()->paging_init()->bootmem_init()->bootmem_free_node()->free_area_init_node()->free_area_init_core()->zone_pcp_init()
Normal zone: 85344 pages, LIFO batch:15
2.2.11 setup_arch()->paging_init()->devicemaps_init()->msm7x2x_map_io()->
allocating 28794880 bytes at c1301000 (14301000 physical) for mdp pmem arena
allocating 10346496 bytes at c2e77000 (15e77000 physical) for adsp pmem arena
allocating 372736 bytes (at 80000 physical) for audio pmem arena
allocating 655360 bytes at c3855000 (16855000 physical) for fb
allocating 114688 bytes at c3900000 (16900000 physical) for kernel ebi1 pmem arena
2.2.12 setup_arch()->paging_init()->devicemaps_init()->msm7x2x_map_io()->l2x0_init()
L210 cache controller enabled
2.3 start_kernel()->build_all_zonelists()
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 85344
2.4 start_kernel()
Kernel command line: mem=336M console=NULL hw=1 fbaddr=0xc8000
2.5 start_kernel()->pidhash_init()->alloc_large_system_hash()
PID hash table entries: 2048 (order: 1, 8192 bytes)
2.6 start_kernel()->vfs_caches_init_early()->dcache_init_early()->alloc_large_system_hash()
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
2.6 start_kernel()->vfs_caches_init_early()->inode_init_early()->alloc_large_system_hash()
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
2.7 start_kernel()->sort_main_extable()->sort_extable()
c0678000 D __start___ex_table
c0678000 D tasklist_lock
c0679070 D __stop___ex_table
2.8.1 start_kernel()->mm_init()->mem_init()
Memory: 336MB = 336MB total
Memory: 289856k/289856k available, 54208k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xffc00000 - 0xffe00000 ( 2 MB)
vmalloc : 0xd5800000 - 0xf0000000 ( 424 MB)
lowmem : 0xc0000000 - 0xd5000000 ( 336 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.init : 0xc0008000 - 0xc0031000 ( 164 kB)
.text : 0xc0031000 - 0xc0674000 (6412 kB)
.data : 0xc0674000 - 0xc06e33c0 ( 445 kB)
2.8.2 start_kernel()->mm_init()->kmem_cache_init()
Initialisation. Called after the page allocator have been initialised and before smp_init().
/* Bootstrap is tricky, because several objects are allocated
* from caches that do not exist yet:
* 1) initialize the cache_cache cache: it contains the struct
* kmem_cache structures of all caches, except cache_cache itself:
* cache_cache is statically allocated.
* Initially an __init data area is used for the head array and the
* kmem_list3 structures, it's replaced with a kmalloc allocated
* array at the end of the bootstrap.
* 2) Create the first kmalloc cache.
* The struct kmem_cache for the new cache is allocated normally.
* An __init data area is used for the head array.
* 3) Create the remaining kmalloc caches, with minimally sized
* head arrays.
* 4) Replace the __init data head arrays for cache_cache and the first
* kmalloc cache with kmalloc allocated arrays.
* 5) Replace the __init data for kmem_list3 for cache_cache and
* the other cache's with kmalloc allocated memory.
* 6) Resize the head arrays of the kmalloc caches to their final sizes.--------->kmem_cache_init_late()
*/
2.9 start_kernel()->sched_init()
Set up the scheduler prior starting any interrupts (such as the timer interrupt). Full topology setup happens at smp_init() time - but meanwhile we still have a functioning scheduler.
2.10 start_kernel()->preempt_disable()
Disable preemption - early bootup scheduling is extremely fragile until we cpu_idle() for the first time.
2.11.1 start_kernel()->rcu_init()->rcu_bootup_announce()
Hierarchical RCU implementation.
2.11.2 start_kernel()->rcu_init()->rcu_bootup_announce()->rcu_bootup_announce_oddness()
RCU-based detection of stalled CPUs is disabled.
Verbose stalled-CPUs detection is disabled.
2.12 start_kernel()->radix_tree_init()
2.13 start_kernel()->early_irq_init() /* init some links before init_ISA_irqs() */
NR_IRQS:261
2.14 start_kernel()->init_IRQ()
init_arch_irq = mdesc->init_irq;------------------>msm7x2x_init_irq()
2.15 start_kernel()->prio_tree_init()
init index_bits_to_maxindex
2.16 start_kernel()->init_timers()
CPU_UP_PREPARE open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
2.17 start_kernel()->hrtimers_init()
CPU_UP_PREPARE open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
2.18 start_kernel()->softirq_init()
open_softirq(TASKLET_SOFTIRQ, tasklet_action);
open_softirq(HI_SOFTIRQ, tasklet_hi_action);
2.19 start_kernel()->timekeeping_init()
2.20 start_kernel()->time_init()
mdesc->timer->init()-------->msm_timer_init() init sched_clock_update_fn=msm_update_sched_clock
sched_clock: 27 bits at 600kHz, resolution 1666ns, wraps every 223696ms
2.21 start_kernel()->profile_init()
2.22 start_kernel()->kmem_cache_init_late()
2.23 start_kernel()->console_init()
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
__con_initcall_start
__initcall_con_init-------->con_init()
Console: colour dummy device 80x30
__initcall_end
__con_initcall_end
2.24 start_kernel()->idr_init_cache()
kmem_cache_create("idr_layer_cache",
2.25 start_kernel()->calibrate_delay()
Calibrating delay loop... 599.65 BogoMIPS (lpj=2998272)
2.25 start_kernel()->pidmap_init()
pid_max: default: 32768 minimum: 301
2.26 start_kernel()->anon_vma_init()
kmem_cache_create("anon_vma",
KMEM_CACHE(anon_vma_chain,
---------------------------------
thread_info_cache_init();
---------------------------------
2.27 start_kernel()->cred_init()
kmem_cache_create("cred_jar"
2.28 start_kernel()->fork_init()
kmem_cache_create("task_struct"
2.29 start_kernel()->proc_caches_init()
kmem_cache_create("sighand_cache",
kmem_cache_create("signal_cache",
kmem_cache_create("files_cache",
kmem_cache_create("fs_cache",
kmem_cache_create("mm_struct",
KMEM_CACHE(vm_area_struct
2.30 start_kernel()->buffer_init()
kmem_cache_create("buffer_head",
---------------------------------
key_init()
security_init()
dbg_late_init()
---------------------------------
2.31.1 start_kernel()->vfs_caches_init()
kmem_cache_create("names_cache",
2.31.2 start_kernel()->vfs_caches_init()->files_init()
kmem_cache_create("filp"
2.31.3 start_kernel()->vfs_caches_init()->mnt_init()
kmem_cache_create("mnt_cache"
Mount-cache hash table entries: 512
kobject_create_and_add("fs"
2.31.4 start_kernel()->vfs_caches_init()->bdev_cache_init()
kmem_cache_create("bdev_cache"
2.32 start_kernel()->signals_init()
KMEM_CACHE(sigqueue
--------------------------------------
signals_init()
page_writeback_init()
--------------------------------------
2.33 start_kernel()->proc_root_init()
init the system dir and link
2.34.1 start_kernel()->cgroup_init()
Register cgroup filesystem and /proc file, and initialize any subsystems that didn't request early init.
2.34.2 start_kernel()->cgroup_init()->cgroup_init_subsys()
Initializing cgroup subsys cpuacct
Initializing cgroup subsys freezer
#define SUBSYS(_x) &_x ## _subsys,
static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {
#include <linux/cgroup_subsys.h>
};
--------------------------------------
cpuset_init()
taskstats_init_early()
delayacct_init()
--------------------------------------
2.35 start_kernel()->cgroup_init()->check_bugs()
#define check_bugs() check_writebuffer_bugs()
CPU: Testing write buffer coherency: ok
--------------------------------------
acpi_early_init()
sfi_init_late()
ftrace_init()
--------------------------------------
2.35 start_kernel()->rest_init()
Do the rest non-__init'ed, we're now alive
kernel boot部分请参加以下两个参考资料
The Kernel Boot Process
Linux内核启动过程(2.6.23) bootloader部分