歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> Linux核心代碼分析

Linux核心代碼分析

日期:2017/2/27 9:40:51   编辑:更多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; }




Copyright © Linux教程網 All Rights Reserved