⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jjj-start_kernel.txt

📁 (系统初始化start_kernel函数)
💻 TXT
字号:
(系统初始化start_kernel函数) 

作者:大鹰mailto:e4gle@hackermail.com 

至于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; 
} 

原作者:大鹰 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -