机电之家资源网
单片机首页|单片机基础|单片机应用|单片机开发|单片机文案|软件资料下载|音响制作|电路图下载 |嵌入式开发
培训信息
赞助商
linux核心代码分析(系统初始化start_kernel函数)
linux核心代码分析(系统初始化start_kernel函数)
 更新时间:2009-8-12 16:57:25  点击数:0
【字体: 字体颜色
至于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;
}


 补充日期: 2001-04-03 22:15:27

我觉得我还是不适合写文章,在搞定linux的核心初始化和freebsd的初始化后只能写出这点东东来,呵呵
 
里面牵涉到的结构之多足以使我眼花缭乱,呵呵,也费不了太多唇舌来解释每个结构,那是会死人的,主要向大家
介绍一下linux的核心是如何自我启动的,呵呵
  • 上一篇: 让linux支持你的DMA66硬盘
  • 下一篇: 寻找Linux下的网络邻居(图形工具:gnomba,Tk Samba,xSMBrowser,LinNeighborhood)
  • 发表评论   告诉好友   打印此文  收藏此页  关闭窗口  返回顶部
    热点文章
     
    推荐文章
     
    相关文章
    网友评论:(只显示最新5条。)
    关于我们 | 联系我们 | 广告合作 | 付款方式 | 使用帮助 | 机电之家 | 会员助手 | 免费链接

    点击这里给我发消息66821730(技术支持)点击这里给我发消息66821730(广告投放) 点击这里给我发消息41031197(编辑) 点击这里给我发消息58733127(审核)
    本站提供的机电设备,机电供求等信息由机电企业自行提供,该企业负责信息内容的真实性、准确性和合法性。
    机电之家对此不承担任何保证责任,有侵犯您利益的地方请联系机电之家,机电之家将及时作出处理。
    Copyright 2007 机电之家 Inc All Rights Reserved.机电之家-由机电一体化网更名-声明
    电话:0571-87774297 传真:0571-87774298
    杭州滨兴科技有限公司提供技术支持

    主办:杭州市高新区(滨江)机电一体化学会
    中国行业电子商务100强网站

    网站经营许可证:浙B2-20080178-1