今天开始读内核,立帖纪念! 2.4.0 asmlinkage void __init start_kernel(void) { char * command_line; unsigned long mempages; extern char saved_command_line[]; /* * Interrupts are still disabled. Do necessary setups, then * enable them */ /*锁内核*/ lock_kernel(); /*打印内核的版本和编译的信息*/ printk(linux_banner); /*解析内核的命令行中与内存相关的信息和内存分布信息*/ setup_arch(&command_line); /*打印命令行信息*/ printk("Kernel command line: %s\n", saved_command_line); /*解析传递给内核的命令行中的0号进程的程序名和环境变量*/ parse_options(command_line); /*常用中断,异常的初始化*/ trap_init(); /*非常用的中断初始化*/ init_IRQ(); /*调度相关的计时器和底半部的初始化*/ sched_init(); /*时钟初始化*/ time_init(); /*软中断tasklet初始化*/ softirq_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. */ /*终端初始化*/ console_init(); #ifdef CONFIG_MODULES /*初始化模块symbol表大小*/ init_modules(); #endif if (prof_shift) { unsigned int size; /* only text is profiled */ prof_len = (unsigned long) &_etext - (unsigned long) &_stext; prof_len >>= prof_shift; size = prof_len * sizeof(unsigned int) PAGE_SIZE-1; prof_buffer = (unsigned int *) alloc_bootmem(size); } /*初始化slab分配器*/ kmem_cache_init(); sti(); calibrate_delay(); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && initrd_start need_resched = 1; /*运行idle进程,进行调度*/ cpu_idle(); } void __init setup_arch(char **cmdline_p) { unsigned long bootmap_size; unsigned long start_pfn, max_pfn, max_low_pfn; int i; #ifdef CONFIG_VISWS visws_get_board_type_and_rev(); #endif /*将rootfs转化成kdev的表示形式,这里跟传统的表示没有不同*/ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; apm_info.bios = APM_BIOS_INFO; /*将系统的描述信息写入全局变量中*/ if( SYS_DESC_TABLE.length != 0 ) { MCA_bus = SYS_DESC_TABLE.table[3] &0x2; machine_id = SYS_DESC_TABLE.table[0]; machine_submodel_id = SYS_DESC_TABLE.table[1]; BIOS_revision = SYS_DESC_TABLE.table[2]; } aux_device_present = AUX_DEVICE_INFO; #ifdef CONFIG_BLK_DEV_RAM /*设置RAMDISK的标志*/ rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); #endif setup_memory_region(); if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; /*在init_mm存放数据段,代码段和堆栈段的起始地址,结束地址*/ init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; /*存放内核和数据段的起始和结束地址,这里是转化为物理地址存放的*/ code_resource.start = virt_to_bus(&_text); code_resource.end = virt_to_bus(&_etext)-1; data_resource.start = virt_to_bus(&_etext); data_resource.end = virt_to_bus(&_edata)-1; /*解析命令行中的"mem="参数*/ parse_mem_cmdline(cmdline_p); #define PFN_UP(x) (((x) PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) = end) continue; if (end > max_pfn) max_pfn = end; } /* * Determine low and high memory ranges: */ /*找到最高的低端物理页号,既896M对应的物理页号*/ max_low_pfn = max_pfn; if (max_low_pfn > MAXMEM_PFN) { max_low_pfn = MAXMEM_PFN; #ifndef CONFIG_HIGHMEM /* Maximum memory usable is what is directly addressable */ printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20); if (max_pfn > MAX_NONPAE_PFN) printk(KERN_WARNING "Use a PAE enabled kernel.\n"); else printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); #else /* !CONFIG_HIGHMEM */ #ifndef CONFIG_X86_PAE if (max_pfn > MAX_NONPAE_PFN) { max_pfn = MAX_NONPAE_PFN; printk(KERN_WARNING "Warning only 4GB will be used.\n"); printk(KERN_WARNING "Use a PAE enabled kernel.\n"); } #endif /* !CONFIG_X86_PAE */ #endif /* !CONFIG_HIGHMEM */ } /*设置高端内存的起始和结束地址*/ #ifdef CONFIG_HIGHMEM highstart_pfn = highend_pfn = max_pfn; if (max_pfn > MAXMEM_PFN) { highstart_pfn = MAXMEM_PFN; printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", pages_to_mb(highend_pfn - highstart_pfn)); } #endif /* * Initialize the boot-time allocator (with low memory only): */ /*初始化896M以下的boot内存*/ bootmap_size = init_bootmem(start_pfn, max_low_pfn); /* * Register fully available low RAM pages with the bootmem allocator. */ /*将896M以下的内存设为可用状态*/ for (i = 0; i = max_low_pfn) continue; /* * ... and at the end of the usable range downwards: */ last_pfn = PFN_DOWN(e820.map.addr e820.map.size); if (last_pfn > max_low_pfn) last_pfn = max_low_pfn; /* * .. finally, did all the rounding and playing * around just make the area go away? */ if (last_pfn 0x lx)\ndisabling initrd\n", INITRD_START INITRD_SIZE, max_low_pfn 0x100000000ULL) continue; res = alloc_bootmem_low(sizeof(struct resource)); switch (e820.map.type) { case E820_RAM: res->name = "System RAM"; break; case E820_ACPI: res->name = "ACPI Tables"; break; case E820_NVS: res->name = "ACPI Non-volatile Storage"; break; default: res->name = "reserved"; } res->start = e820.map.addr; res->end = res->start e820.map.size - 1; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); if (e820.map.type == E820_RAM) { /* * We dont't know which RAM region contains kernel data, * so we try it repeatedly and let the resource manager * test it. */ request_resource(res, &code_resource); request_resource(res, &data_resource); } } request_resource(&iomem_resource, &vram_resource); /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i setup_arch->setup_memory_region 这个表示调用关系 void __init setup_memory_region(void) { char *who = "BIOS-e820"; /* * Try to copy the BIOS-supplied E820-map. * * Otherwise fake a memory map; one section from 0k->640k, * the next section from 1mb->appropriate_mem_k */ /*拷贝E820得到的内存分配图,如果E820没有获得内存分配图,自己创造一个分布图*/ if (copy_e820_map(E820_MAP, E820_MAP_NR) setup_memory_region->copy_e820_map /* * Copy the BIOS e820 map into a safe place. * * Sanity-check it while we're at it.. * * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly * set up memory. If we aren't, we'll fake a memory map. * * We check to see that the memory map contains at least 2 elements * before we'll use it, because the detection code in setup.S may * not be perfect and most every PC known to man has two memory * regions: one from 0 to 640k, and one from 1mb up. (The IBM * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) { /* Only one memory region (or negative)? Ignore it */ if (nr_map addr; unsigned long long size = biosmap->size; unsigned long long end = start size; unsigned long type = biosmap->type; /* Overflow in 64 bits? Ignore the memory map. */ if (start > end) return -1; /* * Some BIOSes claim RAM in the 640k - 1M region. * Not right. Fix it up. */ /*将跨0xA0000-0x100000的内存分开,这一段是系统使用的*/ if (type == E820_RAM) { if (start 0xA0000ULL) { if (start setup_memory_region->copy_e820_map->add_memory_region void __init add_memory_region(unsigned long long start, unsigned long long size, int type) { int x = e820.nr_map; if (x == E820MAX) { printk("Ooops! Too many entries in the memory map!\n"); return; } /*记录内存分布的开始,大小和类型*/ e820.map[x].addr = start; e820.map[x].size = size; e820.map[x].type = type; e820.nr_map ; } /* add_memory_region */ start_kernel->setup_arch->parse_mem_cmdline static inline void parse_mem_cmdline (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; int usermem = 0; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; for (;;) { /* * "mem=nopentium" disables the 4MB page tables. * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM * to , overriding the bios size. * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from * to , overriding the bios size. */ /*解析mem=参数*/ if (c == ' ' && !memcmp(from, "mem=", 4)) { if (to != command_line) to--; /*如果是mem=nopentium,将PSE的标志去掉*/ if (!memcmp(from 4, "nopentium", 9)) { from = 9 4; clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability); /*通过exactmap, mem=xxxx@XXXX,完全使用命令行上指定的参数*/ } else if (!memcmp(from 4, "exactmap", 8)) { from = 8 4; e820.nr_map = 0; usermem = 1; } else { /* If the user specifies memory size, we * blow away any automatically generated * size */ unsigned long start_at, mem_size; /*如果命令行没有指定exactmap参数,将0-0x9f000加入到内存分布表中*/ if (usermem == 0) { /* first time in: zap the whitelist * and reinitialize it with the * standard low-memory region. */ e820.nr_map = 0; usermem = 1; add_memory_region(0, LOWMEMSIZE(), E820_RAM); } /*解析出内存块的大小*/ mem_size = memparse(from 4, &from); /*解析出内存块的开始地址,如果没指定就用1M做为起始地址*/ if (*from == '@') start_at = memparse(from 1, &from); else { start_at = HIGH_MEMORY; mem_size -= HIGH_MEMORY; usermem=0; } /*将内存块加入到内存分布表中*/ add_memory_region(start_at, mem_size, E820_RAM); } } c = *(from ); if (!c) break; if (COMMAND_LINE_SIZE setup_arch->setup_memory_region 这个表示调用关系 void __init setup_memory_region(void) { char *who = "BIOS-e820"; /* * Try to copy the BIOS-supplied E820-map. * * Otherwise fake a memory map; one section from 0k->640k, * the next section from 1mb->appropriate_mem_k */ /*拷贝E820得到的内存分配图,如果E820没有获得内存分配图,自己创造一个分布图*/ if (copy_e820_map(E820_MAP, E820_MAP_NR) setup_memory_region->copy_e820_map /* * Copy the BIOS e820 map into a safe place. * * Sanity-check it while we're at it.. * * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly * set up memory. If we aren't, we'll fake a memory map. * * We check to see that the memory map contains at least 2 elements * before we'll use it, because the detection code in setup.S may * not be perfect and most every PC known to man has two memory * regions: one from 0 to 640k, and one from 1mb up. (The IBM * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) { /* Only one memory region (or negative)? Ignore it */ if (nr_map addr; unsigned long long size = biosmap->size; unsigned long long end = start size; unsigned long type = biosmap->type; /* Overflow in 64 bits? Ignore the memory map. */ if (start > end) return -1; /* * Some BIOSes claim RAM in the 640k - 1M region. * Not right. Fix it up. */ /*将跨0xA0000-0x100000的内存分开,这一段是系统使用的*/ if (type == E820_RAM) { if (start 0xA0000ULL) { if (start setup_memory_region->copy_e820_map->add_memory_region void __init add_memory_region(unsigned long long start, unsigned long long size, int type) { int x = e820.nr_map; if (x == E820MAX) { printk("Ooops! Too many entries in the memory map!\n"); return; } /*记录内存分布的开始,大小和类型*/ e820.map[x].addr = start; e820.map[x].size = size; e820.map[x].type = type; e820.nr_map ; } /* add_memory_region */ start_kernel->setup_arch->parse_mem_cmdline static inline void parse_mem_cmdline (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; int usermem = 0; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; for (;;) { /* * "mem=nopentium" disables the 4MB page tables. * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM * to , overriding the bios size. * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from * to , overriding the bios size. */ /*解析mem=参数*/ if (c == ' ' && !memcmp(from, "mem=", 4)) { if (to != command_line) to--; /*如果是mem=nopentium,将PSE的标志去掉*/ if (!memcmp(from 4, "nopentium", 9)) { from = 9 4; clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability); /*通过exactmap, mem=xxxx@XXXX,完全使用命令行上指定的参数*/ } else if (!memcmp(from 4, "exactmap", 8)) { from = 8 4; e820.nr_map = 0; usermem = 1; } else { /* If the user specifies memory size, we * blow away any automatically generated * size */ unsigned long start_at, mem_size; /*如果命令行没有指定exactmap参数,将0-0x9f000加入到内存分布表中*/ if (usermem == 0) { /* first time in: zap the whitelist * and reinitialize it with the * standard low-memory region. */ e820.nr_map = 0; usermem = 1; add_memory_region(0, LOWMEMSIZE(), E820_RAM); } /*解析出内存块的大小*/ mem_size = memparse(from 4, &from); /*解析出内存块的开始地址,如果没指定就用1M做为起始地址*/ if (*from == '@') start_at = memparse(from 1, &from); else { start_at = HIGH_MEMORY; mem_size -= HIGH_MEMORY; usermem=0; } /*将内存块加入到内存分布表中*/ add_memory_region(start_at, mem_size, E820_RAM); } } c = *(from ); if (!c) break; if (COMMAND_LINE_SIZE |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-29 21:19 , Processed in 0.167805 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.