(一)start函数分析

 

Start_kernel()中调用了一系列初始化函数,以完成kernel本身的设置。这些动作有的是公共的,有的则是需要配置的才会执行的。

在start_kernel()函数中,

输出Linux版本信息(printk(linux_banner))

设置与体系结构相关的环境(setup_arch())

页表结构初始化(paging_init())

使用"arch/alpha/kernel/entry.S"中的入口点设置系统自陷入口(trap_init())

使用alpha_mv结构和entry.S入口初始化系统IRQ(init_IRQ())

核心进程调度器初始化(包括初始化几个缺省的Bottom-half,sched_init())

时间、定时器初始化(包括读取CMOS时钟、估测主频、初始化定时器中断等,time_init())

提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options())

控制台初始化(为输出信息而先于PCI初始化,console_init())

剖析器数据结构初始化(prof_buffer和prof_len变量)

核心Cache初始化(描述Cache信息的Cache,kmem_cache_init())

延迟校准(获得时钟jiffies与CPU主频ticks的延迟,calibrate_delay())

内存初始化(设置内存上下界和页表项初始值,mem_init())

创建和设置内部及通用cache("slab_cache",kmem_cache_sizes_init())

创建uid taskcount SLAB cache("uid_cache",uidcache_init())

创建文件cache("files_cache",filescache_init())

创建目录cache("dentry_cache",dcache_init())

创建与虚存相关的cache("vm_area_struct","mm_struct",vma_init())

块设备读写缓冲区初始化(同时创建"buffer_head"cache用户加速访问,buffer_init())

创建页cache(内存页hash表初始化,page_cache_init())

创建信号队列cache("signal_queue",signals_init())

初始化内存inode表(inode_init())

创建内存文件描述符表("filp_cache",file_table_init())

检查体系结构漏洞(对于alpha,此函数为空,check_bugs())

SMP机器其余CPU(除当前引导CPU)初始化(对于没有配置SMP的内核,此函数为空,smp_init())

启动init过程(创建第一个核心线程,调用init()函数,原执行序列调用cpu_idle() 等待调度,init())

至此start_kernel()结束,基本的核心环境已经建立起来了。

 

  1. asmlinkage void __init start_kernel(void)  
  2. {  
  3.         char * command_line;  
  4.         unsigned long mempages;  
  5.         extern char saved_command_line[];  
  6. /* 
  7.  * Interrupts are still disabled. Do necessary setups, then 
  8.  * enable them 
  9.  */  
  10.         /*锁内核*/  
  11.         lock_kernel();  
  12.         /*打印内核的版本和编译的信息*/  
  13.         printk(linux_banner);  
  14.         /*解析内核的命令行中与内存相关的信息和内存分布信息*/  
  15.         setup_arch(&command_line);  
  16.         /*打印命令行信息*/  
  17.         printk("Kernel command line: %s/n", saved_command_line);  
  18.         /*解析传递给内核的命令行中的0号进程的程序名和环境变量*/  
  19.         parse_options(command_line);  
  20.         /*常用中断,异常的初始化*/  
  21.         trap_init();  
  22.         /*非常用的中断初始化*/  
  23.         init_IRQ();  
  24.         /*调度相关的计时器和底半部的初始化*/  
  25.         sched_init();  
  26.         /*时钟初始化*/  
  27.         time_init();  
  28.         /*软中断tasklet初始化*/  
  29.         softirq_init();  
  30.         /* 
  31.         * HACK ALERT! This is early. We're enabling the console before 
  32.         * we've done PCI setups etc, and console_init() must be aware of 
  33.         * this. But we do want output early, in case something goes wrong. 
  34.         */  
  35.         /*终端初始化*/  
  36.         console_init();  
  37. #ifdef CONFIG_MODULES   
  38.         /*初始化模块symbol表大小*/  
  39.         init_modules();  
  40. #endif   
  41.         if (prof_shift) {  
  42.                unsigned int size;  
  43.                /* only text is profiled */  
  44.                prof_len = (unsigned long) &_etext - (unsigned long) &_stext;  
  45.                prof_len >>= prof_shift;  
  46.                 
  47.                size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;  
  48.                prof_buffer = (unsigned int *) alloc_bootmem(size);  
  49.         }  
  50.         /*初始化slab分配器*/  
  51.         kmem_cache_init();  
  52.         sti();  
  53.         calibrate_delay();  
  54. #ifdef CONFIG_BLK_DEV_INITRD   
  55.         if (initrd_start && !initrd_below_start_ok &&  
  56.                        initrd_start < min_low_pfn << PAGE_SHIFT) {  
  57.                printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "  
  58.                    "disabling it./n",initrd_start,min_low_pfn << PAGE_SHIFT);  
  59.                initrd_start = 0;  
  60.         }  
  61. #endif   
  62.         /*设置高端内存和内存的标志位*/  
  63.         mem_init();     
  64.         /*初始化内部和一般的slab分配器*/  
  65.         kmem_cache_sizes_init();  
  66. #ifdef CONFIG_3215_CONSOLE   
  67.         con3215_activate();  
  68. #endif   
  69. #ifdef CONFIG_PROC_FS   
  70.         /*建立proc文件系统的目录*/  
  71.         proc_root_init();  
  72. #endif   
  73.         mempages = num_physpages;  
  74.         /*初始化最大线程数*/  
  75.         fork_init(mempages);  
  76.         /*创建一些常用的slab分配器的数据结构*/  
  77.         proc_caches_init();  
  78.         vfs_caches_init(mempages);  
  79.         /*初始化buffer数据结构*/  
  80.         buffer_init(mempages);  
  81.         /*初始化页表的缓冲结构*/  
  82.         page_cache_init(mempages);  
  83.         kiobuf_setup();  
  84.         /*创建signal的slab数据结构*/  
  85.         signals_init();  
  86.         bdev_init();  
  87.         /*初始化文件系统的inode结构*/  
  88.         inode_init(mempages);  
  89. #if defined(CONFIG_SYSVIPC)   
  90.         /*初始化sysv的信号量,消息,共享内存*/  
  91.         ipc_init();  
  92. #endif   
  93. #if defined(CONFIG_QUOTA)   
  94.         dquot_init_hash();  
  95. #endif   
  96.         check_bugs();  
  97.         printk("POSIX conformance testing by UNIFIX/n");  
  98.    
  99.         /* 
  100.          *      We count on the initial thread going ok 
  101.          *      Like idlers init is an unlocked kernel thread, which will 
  102.         *      make syscalls (and thus be locked). 
  103.         */  
  104.         /*初始化SMP,主要是APIC的初始化*/  
  105.         smp_init();  
  106.         /*创建init进程*/  
  107.         kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);  
  108.         unlock_kernel();  
  109.         current->need_resched = 1;  
  110.         /*运行idle进程,进行调度*/  
  111.         cpu_idle();  
  112. }  
  113. void __init setup_arch(char **cmdline_p)  
  114. {  
  115.         unsigned long bootmap_size;  
  116.         unsigned long start_pfn, max_pfn, max_low_pfn;  
  117.         int i;  
  118.    
  119. #ifdef CONFIG_VISWS   
  120.         visws_get_board_type_and_rev();  
  121. #endif   
  122.         /*将rootfs转化成kdev的表示形式,这里跟传统的表示没有不同*/  
  123.         ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);  
  124.         drive_info = DRIVE_INFO;  
  125.         screen_info = SCREEN_INFO;  
  126.         apm_info.bios = APM_BIOS_INFO;  
  127.         /*将系统的描述信息写入全局变量中*/  
  128.         if( SYS_DESC_TABLE.length != 0 ) {  
  129.                MCA_bus = SYS_DESC_TABLE.table[3] &0x2;  
  130.                machine_id = SYS_DESC_TABLE.table[0];  
  131.                machine_submodel_id = SYS_DESC_TABLE.table[1];  
  132.                BIOS_revision = SYS_DESC_TABLE.table[2];  
  133.         }  
  134.         aux_device_present = AUX_DEVICE_INFO;  
  135.    
  136. #ifdef CONFIG_BLK_DEV_RAM   
  137.         /*设置RAMDISK的标志*/  
  138.         rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;  
  139.         rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);  
  140.         rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);  
  141. #endif   
  142.         setup_memory_region();  
  143.    
  144.         if (!MOUNT_ROOT_RDONLY)  
  145.                root_mountflags &= ~MS_RDONLY;  
  146.         /*在init_mm存放数据段,代码段和堆栈段的起始地址,结束地址*/  
  147.         init_mm.start_code = (unsigned long) &_text;  
  148.         init_mm.end_code = (unsigned long) &_etext;  
  149.         init_mm.end_data = (unsigned long) &_edata;  
  150.         init_mm.brk = (unsigned long) &_end;  
  151.    
  152.         /*存放内核和数据段的起始和结束地址,这里是转化为物理地址存放的*/  
  153.         code_resource.start = virt_to_bus(&_text);  
  154.         code_resource.end = virt_to_bus(&_etext)-1;  
  155.         data_resource.start = virt_to_bus(&_etext);  
  156.         data_resource.end = virt_to_bus(&_edata)-1;  
  157.    
  158.         /*解析命令行中的"mem="参数*/  
  159.         parse_mem_cmdline(cmdline_p);  
  160.    
  161. #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)   
  162. #define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)   
  163. #define PFN_PHYS(x)    ((x) << PAGE_SHIFT)   
  164.    
  165. /* 
  166.  * 128MB for vmalloc and initrd 
  167.  */  
  168. #define VMALLOC_RESERVE        (unsigned long)(128 << 20)   
  169. #define MAXMEM         (unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)   
  170. #define MAXMEM_PFN     PFN_DOWN(MAXMEM)   
  171. #define MAX_NONPAE_PFN (1 << 20)   
  172.         /* 
  173.         * partially used pages are not usable - thus 
  174.         * we are rounding upwards: 
  175.         */  
  176.         /*找到起始物理页号*/  
  177.         start_pfn = PFN_UP(__pa(&_end));  
  178.    
  179.         /* 
  180.         * Find the highest page frame number we have available 
  181.         */  
  182.         /*从E820中找到最高物理页号*/  
  183.         max_pfn = 0;  
  184.         for (i = 0; i < e820.nr_map; i++) {  
  185.                unsigned long start, end;  
  186.                /* RAM? */  
  187.                if (e820.map[i].type != E820_RAM)  
  188.                        continue;  
  189.                start = PFN_UP(e820.map[i].addr);  
  190.                end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);  
  191.                if (start >= end)  
  192.                        continue;  
  193.                if (end > max_pfn)  
  194.                        max_pfn = end;  
  195.         }  
  196.    
  197.         /* 
  198.         * Determine low and high memory ranges: 
  199.         */  
  200.         /*找到最高的低端物理页号,既896M对应的物理页号*/  
  201.         max_low_pfn = max_pfn;  
  202.         if (max_low_pfn > MAXMEM_PFN) {  
  203.                max_low_pfn = MAXMEM_PFN;  
  204. #ifndef CONFIG_HIGHMEM   
  205.                /* Maximum memory usable is what is directly addressable */  
  206.                printk(KERN_WARNING "Warning only %ldMB will be used./n",  
  207.                                       MAXMEM>>20);  
  208.                if (max_pfn > MAX_NONPAE_PFN)  
  209.                        printk(KERN_WARNING "Use a PAE enabled kernel./n");  
  210.                else  
  211.                        printk(KERN_WARNING "Use a HIGHMEM enabled kernel./n");  
  212. #else /* !CONFIG_HIGHMEM */   
  213. #ifndef CONFIG_X86_PAE   
  214.                if (max_pfn > MAX_NONPAE_PFN) {  
  215.                        max_pfn = MAX_NONPAE_PFN;  
  216.                        printk(KERN_WARNING "Warning only 4GB will be used./n");  
  217.                        printk(KERN_WARNING "Use a PAE enabled kernel./n");  
  218.                }  
  219. #endif /* !CONFIG_X86_PAE */   
  220. #endif /* !CONFIG_HIGHMEM */   
  221.         }  
  222.         /*设置高端内存的起始和结束地址*/  
  223. #ifdef CONFIG_HIGHMEM   
  224.         highstart_pfn = highend_pfn = max_pfn;  
  225.         if (max_pfn > MAXMEM_PFN) {  
  226.                highstart_pfn = MAXMEM_PFN;  
  227.                printk(KERN_NOTICE "%ldMB HIGHMEM available./n",  
  228.                        pages_to_mb(highend_pfn - highstart_pfn));  
  229.         }  
  230. #endif   
  231.         /* 
  232.         * Initialize the boot-time allocator (with low memory only): 
  233.         */  
  234.         /*初始化896M以下的boot内存*/  
  235.         bootmap_size = init_bootmem(start_pfn, max_low_pfn);  
  236.    
  237.         /* 
  238.         * Register fully available low RAM pages with the bootmem allocator. 
  239.         */  
  240.         /*将896M以下的内存设为可用状态*/  
  241.         for (i = 0; i < e820.nr_map; i++) {  
  242.                unsigned long curr_pfn, last_pfn, size;  
  243.                 /* 
  244.                * Reserve usable low memory 
  245.                */  
  246.                if (e820.map[i].type != E820_RAM)  
  247.                        continue;  
  248.         /* 
  249.                * We are rounding up the start address of usable memory: 
  250.                */  
  251.                curr_pfn = PFN_UP(e820.map[i].addr);  
  252.                if (curr_pfn >= max_low_pfn)  
  253.                        continue;  
  254.                /* 
  255.                * ... and at the end of the usable range downwards: 
  256.                */  
  257.         last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);  
  258.                if (last_pfn > max_low_pfn)  
  259.                        last_pfn = max_low_pfn;  
  260.                /* 
  261.                * .. finally, did all the rounding and playing 
  262.                * around just make the area go away? 
  263.         */  
  264.                if (last_pfn <= curr_pfn)  
  265.                        continue;  
  266.                size = last_pfn - curr_pfn;  
  267.                free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));  
  268.         }  
  269.         /* 
  270.         * Reserve the bootmem bitmap itself as well. We do this in two 
  271.         * steps (first step was init_bootmem()) because this catches 
  272.         * the (very unlikely) case of us accidentally initializing the 
  273.         * bootmem allocator with an invalid RAM area. 
  274.         */  
  275.         /*保留bootmem自己的内存*/  
  276.         reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +  
  277.                        bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));  
  278.         /* 
  279.         * reserve physical page 0 - it's a special BIOS page on many boxes, 
  280.         * enabling clean reboots, SMP operation, laptop functions. 
  281.         */  
  282.         /*保留第一个物理页*/  
  283.         reserve_bootmem(0, PAGE_SIZE);  
  284. #ifdef CONFIG_SMP   
  285.         /* 
  286.         * But first pinch a few for the stack/trampoline stuff 
  287.         * FIXME: Don't need the extra page at 4K, but need to fix 
  288.         * trampoline before removing it. (see the GDT stuff) 
  289.         */  
  290.         reserve_bootmem(PAGE_SIZE, PAGE_SIZE);  
  291.         smp_alloc_memory(); /* AP processor realmode stacks in low memory*/  
  292. #endif   
  293. #ifdef CONFIG_X86_IO_APIC   
  294.         /* 
  295.         * Find and reserve possible boot-time SMP configuration: 
  296.         */  
  297.         find_smp_config();  
  298. #endif   
  299.         /*初始化构建页表*/  
  300.         paging_init();  
  301. #ifdef CONFIG_X86_IO_APIC   
  302.         /* 
  303.         * get boot-time SMP configuration: 
  304.         */  
  305.         if (smp_found_config)  
  306.                get_smp_config();  
  307. #endif   
  308. #ifdef CONFIG_X86_LOCAL_APIC   
  309.         init_apic_mappings();  
  310. #endif   
  311. #ifdef CONFIG_BLK_DEV_INITRD   
  312.         /*将RAMDISK的空间保留下来*/  
  313.         if (LOADER_TYPE && INITRD_START) {  
  314.                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {  
  315.                        reserve_bootmem(INITRD_START, INITRD_SIZE);  
  316.                        initrd_start =  
  317.                                INITRD_START ? INITRD_START + PAGE_OFFSET : 0;  
  318.                        initrd_end = initrd_start+INITRD_SIZE;  
  319.                }  
  320.                else {  
  321.                        printk("initrd extends beyond end of memory "  
  322.                            "(0x%08lx > 0x%08lx)/ndisabling initrd/n",  
  323.                            INITRD_START + INITRD_SIZE,  
  324.                            max_low_pfn << PAGE_SHIFT);  
  325.                        initrd_start = 0;  
  326.                }  
  327.         }  
  328. #endif   
  329.    
  330.         /* 
  331.         * Request address space for all standard RAM and ROM resources 
  332.         * and also for regions reported as reserved by the e820. 
  333.         */  
  334.         /*将ROM加入资源列表中*/  
  335.         probe_roms();  
  336.         /*将RAM等各种资源加入列表中*/  
  337.         for (i = 0; i < e820.nr_map; i++) {  
  338.                struct resource *res;  
  339.                if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)  
  340.                        continue;  
  341.                res = alloc_bootmem_low(sizeof(struct resource));  
  342.                switch (e820.map[i].type) {  
  343.                case E820_RAM: res->name = "System RAM"break;  
  344.                case E820_ACPI: res->name = "ACPI Tables"break;  
  345.                case E820_NVS: res->name = "ACPI Non-volatile Storage"break;  
  346.                default:       res->name = "reserved";  
  347.                }  
  348.                res->start = e820.map[i].addr;  
  349.                res->end = res->start + e820.map[i].size - 1;  
  350.                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;  
  351.                request_resource(&iomem_resource, res);  
  352.                if (e820.map[i].type == E820_RAM) {  
  353.                        /* 
  354.                        *  We dont't know which RAM region contains kernel data, 
  355.                        *  so we try it repeatedly and let the resource manager 
  356.                        *  test it. 
  357.                        */  
  358.                        request_resource(res, &code_resource);  
  359.                        request_resource(res, &data_resource);  
  360.                }  
  361.         }  
  362.         request_resource(&iomem_resource, &vram_resource);  
  363.         /* request I/O space for devices used on all i[345]86 PCs */  
  364.         for (i = 0; i < STANDARD_IO_RESOURCES; i++)  
  365.                request_resource(&ioport_resource, standard_io_resources+i);  
  366.    
  367. #ifdef CONFIG_VT   
  368. #if defined(CONFIG_VGA_CONSOLE)   
  369.         conswitchp = &vga_con;  
  370. #elif defined(CONFIG_DUMMY_CONSOLE)   
  371.         conswitchp = &dummy_con;  
  372. #endif   
  373. #endif   
  374. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值