start_kernel()函数分析
2011-12-02 00:22
405 查看
转载:http://blog.chinaunix.net/u3/94019/showart_1913184.html asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __stop___param[]; /* * Interrupts are still disabled. Do necessary setups, then * enable them */ lock_kernel(); 如果内核配置成支持抢占,那么在这里禁止抢占,将0号进程的init_thread_info.preempt_count加1; 如果配置成不支持抢占,那么内核全局自选锁kernel_flag上锁。 page_address_init(); 10版本的ARM部分,没有支持高端内存相关代码,空函数。 printk(linux_banner); 将linux_banner的内容打印到log_buf缓冲区中。 setup_arch(&command_line); 函数原型在arch/arm/kernel/setup.c中 根据处理器、硬件平台具体型号设置系统。解析Linux系统命令行,设置0号进程(swapper进程)的内存描述结构init_mm,系统内存管理初始化,统计并注册系统各种资源,其他项目的初始化。 setup_per_cpu_areas(); 为系统中每个处理器的per_cpu变量申请空间。 /* * Mark the boot cpu "online" so that it can call console drivers in * printk() and can access its per-cpu storage. */ smp_prepare_boot_cpu(); /* * 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 ing scheduler. */ sched_init(); 初始化每个处理器的可运行进程队列,设置系统初始化进程即0号进程。 build_all_zonelists(); 建立系统内存页区(zone)链表。 page_alloc_init(); printk("Kernel command line: %s\n", saved_command_line); parse_early_param(); 解析早期格式内核参数。 parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param, &unknown_bootoption); 解析新格式内核参数。 sort_main_extable(); 将放在__start__ex_table到__stop__ex_table之间的*(__ex_table)区中的struct exception_table_entry型全局结构变量按insn成员变量值从小到大排序,即将可能导致缺页异常的指令按其指令二进制代码值从小到大排序。 trap_init(); 把放在.Lcvectors处的系统8个意外的入口跳转指令搬到高端中断向量0xffff0000处,再将从__stubs_start到__stubs_end之间的各种意外初始处理代码搬到0xffff0200处。刷新0xffff0000处1页范围的指令cache,将DOMAIN_USER的访问权限由DOMAIN_MANAGER权限改设置成DOMAIN_CLIENT权限。 rcu_init(); 初始化当前CPU的读、复制、更新数据结构(struct rcu_data)全局变量per_cpu_rcu_data和per_cpu_rcu_bh_data。 init_IRQ(); 初始化系统中支持的最大可能中断数的中断描述结构struct irqdesc变量数组irq_desc[NR_IRQS],把每个结构变量irq_desc 都初始化为预先定义好的坏中断描述结构变量bad_irq_desc,并初始化该中断的连表表头成员结构变量pend. pidhash_init(); 设置系统中每种pid hash表中的hash链表数的移位值全局变量pidhash_shift,将pidhash_shift设置为min(12);分别为每种hash表的连续hash链表表头结构空间申请内存,把申请到的内存虚拟基址分别传给pid_hash (n=0~3),并将每种hash表中的每个hash链表表头结构struct hlist_head中的first成员指针设置成NULL init_timers(); 初始化当前出处理器的时间向量基本结构struct tvec_t_base_s全局变量per_cpu_tvec_bases,初始化per_cpu_tvec_bases的自旋锁成员变量lock。 softirq_init(); 设置系统小任务软件中断行为函数描述结构变量softirq_vec[TASKLET_SOFTIRQ(=6)],将softirq_vec[6]的行动函数指针action指向tasklet_action()函数,参数指针设置为NULL. time_init(); 检查系统定时器描述结构struct sys_timer全局变量system_timer是否为空,如果是将其指向dummy_gettimeoffset()函数。 /* * 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. */ console_init(); 初始化系统的控制台结构,该函数执行后调用printk()函数将log_buf中符合打印级别要求的系统信息打印到控制台上。 if (panic_later) panic(panic_later, panic_param); profile_init(); 对系统剖析作相关初始化,系统剖析用于系统调用。 local_irq_enable(); 将处理器的当前系统状态寄存器CPSR的第7位清0,使能IRQ中断。 #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && initrd_start < min_low_pfn << PAGE_SHIFT) { printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT); initrd_start = 0; } #endif vfs_caches_init_early(); mem_init(); 该函数执行完后不能再用像alloc_bootmem()、alloc_bootmem_low()、alloc_bootmem_pages()等申请低端内存的函数来申请内存,也就不能申请大块的连续物理内存了。 kmem_cache_init(); 执行高速缓存内存管理即slab分配器相关初始化。 numa_policy_init(); if (late_time_init) late_time_init(); calibrate_delay(); 计算机系统的BogMIPS数值,即处理器每秒钟执行的指令数。 pidmap_init(); pgtable_cache_init(); prio_tree_init(); 初始化无符号长整型全局数组index_bits_to_maxindex[BITS_PER_LONG]的每个组员,将每个组员index_bits_to_maxindex 设置成-1,将最后的index_bits_to_maxindex[BITS_PER_LONG-1]设置成~0UL。 anon_vma_init(); 该函数调用kmem_cache_create()函数,为匿名虚拟内存区域链表结构struct anon_vma创建高速缓存内存描述结构kmem_cache_t变量,为该变量命名为“anon_vma",其对象的构造函数指针指向void anon_vma_ctor(void *data,kmem_cache_t *cachep,unsigned long flags)函数,析构函数指针空,将创建的kmem_cache_t结构变量地址传给全局指针anon_vma_chachep。 #ifdef CONFIG_X86 if (efi_enabled) efi_enter_virtual_mode(); #endif fork_init(num_physpages); 执行进程创建相关初始化。 proc_caches_init(); buffer_init(); 调用 kmem_cache_create("buffer_head", sizeof(struct buffer_head), 0, SLAB_PANIC, init_buffer_head, NULL)函数为缓冲区描述结构struct buffer_head创建高速缓存内存描述结构kmem_cache_t变量。 unnamed_dev_init(); 调用并返回idr_init(&unnamed_dev_idr)函数。 security_init(); 打印”安全架构v1.0.0被初始化“。如果没有定义系统哑元安全操作函数组结构全局变量dummy_security_ops,打印错误信息,返回I/O错误。 vfs_caches_init(num_physpages); radix_tree_init(); signals_init(); 调用kmem_cache_create("sigqueue", sizeof(struct sigqueue), __alignof__(struct sigqueue), SLAB_PANIC, NULL, NULL)函数为信号队列结构struct sigqueue创建高速缓存内存描述结构kmem_cache_t变量,名字叫”sigqueue“,不要求其对象按处理器硬件cache line大小对齐,没有定义其对象的构造和析构函数,将创建号的kmem_cache_t结构变量的地址传给全局指针sigqueue_cachep。 /* rootfs populating might need page-writeback */ page_writeback_init(); 统计系统中所有内存节点的通用(NORMAL)内存页区中高页数水印值页数之外的额外内存总页数之和传给buffer_pages。 #ifdef CONFIG_PROC_FS proc_root_init(); 只有在系统支持proc文件系统即配置了CONFIG_PROC_FS选项时才被调用。 #endif check_bugs(); acpi_early_init(); /* before LAPIC and SMP init */ /* Do the rest non-__init'ed, we're now alive */ rest_init(); 该函数创建init()内核进程即1号进程,然后是系统启动进程即0号进程空闲。 } |
相关文章推荐
- Linux 启动代码 Start_kernel()函数分析
- Linux内核分析课程3_start_kernel()函数分析
- linux启动分析---C程序入口函数start_kernel
- start_kernel函数之前的汇编分析
- [Funkunux] Linux_2.6.22.6 内核 start_kernel 函数分析之 rest_init
- Linux内核启动函数start_kernel的简单分析
- start_kernel()函数分析
- [Funkunux] Linux_2.6.22.6 内核start_kernel函数分析之console_init
- [转载] linux启动分析(5)---C程序入口函数start_kernel
- start_kernel函数及init进程创建的简单分析
- (二)start_kernel分析二---之setup_arch()函数分析
- start_kernel 函数分析
- Linux内核中start_kernel函数的分析
- 第3阶段——内核启动分析之start_kernel初始化函数(5)
- Linux--start_kernel()函数分析
- [Funkunux] Linux_2.6.22.6 内核start_kernel函数分析之parse_args
- start_kernel函数之前的汇编分析
- arm linux 从入口到start_kernel 代码分析——head.S分析——4
- linux内核启动1_kernel第一条指令到进入start_kernel()函数
- 走向现代:start_kernel函数