新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > uclinux启动过程详细分析

uclinux启动过程详细分析

作者:时间:2018-08-31来源:网络收藏

本文引用地址:http://www.eepw.com.cn/article/201808/388126.htm

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进程。

_idle(),运行idle进程

接下去做的工作由init()函数来完成。init()首先要锁定内核,然后调用do_basic_setup( )来完成外部设备以及驱动程序的初始化。外设的初始化要根据内核的配置来决定,一般需要做下面的初始化工作:

◆PCI总线初始化。

◆网络初始化。

◆一系列其他设备的初始化。

◆start_context_thread()创建事件管理核心进程keventd。

◆通过do_initcalls()函数来启动任何使用__initcall标识的函数。

◆文件系统初始化。

◆加载文件系统。

在do_basic_setup()调用完成之后,init()会释放初始化函数所用的内存,并且打开/dev/console设备重新定向控制台,让系统调用execve来执行程序init。

到这里为止,Linux 内核的初始化工作已经完成。然后开始用户态进程的初始化。

=============================================================

中内存模块的启动初始化

arch/armnommu/kernel/entry_armv.S是一个汇编文件,他包含了一个kernel_entry的定义,这是整个内核的进入点。在完成某些平台相关的初始化工作之后,执行流程跳转到start_kerne()处。从这里开始考察的内存模块启动初始化是如何实现的。

start_kernel()中与内存模块相关的函数调用流程如下:

setup_arch() paging_init() free_area_init() mem_init()

下面分别分析这些函数各自的功能以及对他们的改造。

(1) setup_arch()

setup_arch()首先根据目前内核所配置的平台向某些特定地址写入特殊字符序列,以完成对特定硬件的初始化,比如工作状态发光二极管、错误和报警发光二极管。



关键词: uClinux cpu 控制器

评论


相关推荐

技术专区

关闭