当前位置:Linux教程 - Linux资讯 - Linux核心代码分析

Linux核心代码分析

  (系统初始化start_kernel函数) 至于x86的引导无非如下步骤: 1,cpu初始化自身,在固定位置执行一条指令。 2,这条指令条转到bios中。 3,bios找到启动设备并获取mbr,该mbr指向我们的lilo 4,bios装载并把控制权交给lilo 5,压缩内核自解压,并把控制权转交给解压内核。 简单点讲,就是cpu成为内核引导程序的引导程序的引导程序的引导程序,西西。 这时内核将跳转到start_kernel是/init/main.c的重点函数,main.c函数很多定义都是为此函数服务的,这里 我简要介绍一下这个函数的初始化流程。 初始化内核: 从start_kernel函数(/init/main.c)开始系统初始化工作,好,我们首先分析这个函数: 函数开始首先: #ifdef __SMP__ static int boot_cpu = 1; /* "current" has been set up, we need to load it now *//*定义双处理器用*/ if (!boot_cpu)   initialize_secondary(); boot_cpu = 0; #endif 定义双处理器。 printk(Linux_banner);    /*打印linux banner*/ 打印内核标题信息。 开始初始化自身的部分组件(包括内存,硬件终端,调度等),我来逐个分析其中的函数: setup_arch(&command_line, &memory_start, &memory_end);/*初始化内存*/ 返回内核参数和内核可用的物理地址范围 函数原型如下: setup_arch(char **, unsigned long *, unsigned long *); 返回内存起始地址: memory_start = paging_init(memory_start,memory_end); 看看paging_init的定义,是初始化请求页: paging_init(unsigned long start_mem, unsigned long end_mem)(会在以后的内存管理子系统分析时详细介 绍) { int i; strUCt memclust_struct * cluster; struct memdesc_struct * memdesc; /* initialize mem_map[] */ start_mem = free_area_init(start_mem, end_mem);/*遍历查找内存的空闲页*/ /* find free clusters, update mem_map[] accordingly */ memdesc = (struct memdesc_struct *)   (hwrpb->mddt_offset + (unsigned long) hwrpb); cluster = memdesc->cluster; for (i = memdesc->numclusters ; i > 0; i--, cluster++) {   unsigned long pfn, nr;   /* Bit 0 is console/PALcode reserved. Bit 1 is    non-volatile memory -- we might want to mark    this for later */   if (cluster->usage & 3)   continue;   pfn = cluster->start_pfn;   if (pfn >= MAP_NR(end_mem)) /* if we overrode mem size */   continue;   nr = cluster->numpages;   if ((pfn + nr) > MAP_NR(end_mem)) /* if override in cluster */   nr = MAP_NR(end_mem) - pfn;   while (nr--)   clear_bit(PG_reserved, &mem_map[pfn++].flags); } memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); return start_mem; } trap_init();   初始化硬件中断 /arch/i386/kernel/traps.c文件里定义此函数 sched_init()   初始化调度 /kernel/sched.c文件里有详细的调度算法(这些会在以后进程管理和调度的结构分析中详细介绍) parse_options(command_line) 分析传给内核的各种选项(随后再详细介绍) memory_start = console_init(memory_start,memory_end) 初始化控制台 memory_start = kmem_cache_init(memory_start, memory_end) 初始化内核内存cache(同样,在以后的内存 管理分析中介绍此函数) sti();接受硬件中断 kernel_thread(init, NULL, CLONE_FS CLONE_FILES CLONE_SIGHAND); current->need_resched = 1; need_resched标志增加,调用schedule(调度里面会详细说明)   cpu_idle(NULL) 进入idle循环以消耗空闲的cpu时间片 已经基本完成内核初始化工作,已经把需要完成的少量责任传递给了init,所身于地工作不过是进入idle循环 以消耗空闲的cpu时间片。所以在这里调用了cpu_idle(NULL),它从不返回,所以当有实际工作好处理时,该函 数就会被抢占。 parse_options函数: static void __init parse_options(char *line)/*参数收集在一条长命令行中,内核被赋给指向该命令行头 部的指针*/ { char *next;      char *quote; int args, envs; if (!*line)   return; args = 0; envs = 1; /* TERM is set to 'linux' by default */ next = line; while ((line = next) != NULL) {         quote = strchr(line,'"');         next = strchr(line, ' ');         while (next != NULL && quote != NULL && quote < next) {                        next = strchr(quote+1, '"');             if (next != NULL) {                 quote = strchr(next+1, '"');                 next = strchr(next+1, ' ');             }         }         if (next != NULL)             *next++ = 0;   /*   * check for kernel options first..   */   if (!strcmp(line,"ro")) {   root_mountflags = MS_RDONLY;   continue;   }   if (!strcmp(line,"rw")) {   root_mountflags &= ~MS_RDONLY;   continue;   }   if (!strcmp(line,"debug")) {   console_loglevel = 10;   continue;   }   if (!strcmp(line,"quiet")) {   console_loglevel = 4;   continue;   }   if (!strncmp(line,"init=",5)) {   line += 5;   execute_command = line;   args = 0;   continue;   }   if (checksetup(line))   continue;     if (strchr(line,'=')) {   if (envs >= MAX_INIT_ENVS)    break;   envp_init[++envs] = line;   } else {   if (args >= MAX_INIT_ARGS)    break;   argv_init[++args] = line;   } } argv_init[args+1] = NULL; envp_init[envs+1] = NULL; }
[1] [2] 下一页 

(出处:http://www.sheup.com)


上一页 [1] [2]