uclinux啟動過程詳細分析
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);
parse_options(command_line);
trap_init();
init_IRQ();
sched_init();
softirq_init();
time_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
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);
}
kmem_cache_init();
sti();
calibrate_delay();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start !initrd_below_start_ok initrd_start 《 min_low_pfn 《《 PAGE_SHIFT)
{
printk(KERN_CRIT “initrd overwritten (0x%08lx 《 0x%08lx) - ”
“disabling it./n”,initrd_start,min_low_pfn 《《 PAGE_SHIFT);
initrd_start = 0;
}
#endif
mem_init();
kmem_cache_sizes_init();
pgtable_cache_init();
mempages = num_physpages;
fork_init(mempages);
proc_caches_init();
vfs_caches_init(mempages);
buffer_init(mempages);
page_cache_init(mempages);
#if defined(CONFIG_ARCH_S390)
ccwcache_init();
#endif
signals_init();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
#if defined(CONFIG_SYSVIPC)
ipc_init();
#endif
check_bugs();
printk(“POSIX conformance testing by UNIFIX/n”);
/*
* We count on the initial thread going ok
Like idlers init is an unlocked kernel thread,which will
* make syscalls (and thus be locked)。
*/
smp_init();
rest_init();
}
內核啟動之后需要執行的第一個函數是start_kernel()(在linux/init/main.c文件中)。
start_kernel()
完成下面一系列初始化的工作。
◆printk(1inux_banner),顯示Linux內核的版本信息。
◆ setup_arch(command_line),做與體系結構相關的初始化工作。
◆ parse_options(command_line),解釋系統參數。
◆ trap_init(),設置系統異常的入口點。
◆ init_IRQ(),初始化系統中斷服務。
◆ sched_init(),系統調度器的初始化。
◆ time_init(),時鐘、定時器初始化。
◆ softirq_init(),系統軟中斷的初始化。
◆console_init(),控制臺初始化。
◆kmem_cache_init(),內核cache的初始化。
◆calibrate_delay(),校準時鐘。
◆mem_init(),內存初始化。
◆kmem_cache_sizes_init(),創建及設置通用cache。
◆fork_init(mempages),建立uidcache,并且根據系統內存大小來確定最大進程數目。
◆buffer_init(mempages),塊設備緩沖區的初始化。初始化一系列的cache。
◆check_bugs(),檢查體系結構漏洞。
◆kernel_thread(init NULL,CLONE_FS | CLONE_FILES | CLONE_SIGNAL),創建第一個核心進程,啟動init進程。
◆cpu_idle(),運行idle進程
接下去做的工作由init()函數來完成。init()首先要鎖定內核,然后調用do_basic_setup( )來完成外部設備以及驅動程序的初始化。外設的初始化要根據內核的配置來決定,一般需要做下面的初始化工作:
◆PCI總線初始化。
◆網絡初始化。
◆一系列其他設備的初始化。
◆start_context_thread()創建事件管理核心進程keventd。
◆通過do_initcalls()函數來啟動任何使用__initcall標識的函數。
◆文件系統初始化。
◆加載文件系統。
在do_basic_setup()調用完成之后,init()會釋放初始化函數所用的內存,并且打開/dev/console設備重新定向控制臺,讓系統調用execve來執行程序init。
到這里為止,Linux 內核的初始化工作已經完成。然后開始用戶態進程的初始化。
=============================================================
uClinux中內存模塊的啟動初始化
arch/armnommu/kernel/entry_armv.S是一個匯編文件,他包含了一個kernel_entry的定義,這是整個內核的進入點。在完成某些平臺相關的初始化工作之后,執行流程跳轉到start_kerne()處。從這里開始考察uClinux的內存模塊啟動初始化是如何實現的。
start_kernel()中與內存模塊相關的函數調用流程如下:
setup_arch() paging_init() free_area_init() mem_init()
下面分別分析這些函數各自的功能以及uClinux對他們的改造。
(1) setup_arch()
setup_arch()首先根據目前內核所配置的平臺向某些特定地址寫入特殊字符序列,以完成對特定硬件的初始化,比如工作狀態發光二極管、錯誤和報警發光二極管。
評論