基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程二
来源:互联网 发布:大数据理论研究 编辑:程序博客网 时间:2024/05/29 15:17
接下来介绍main.c 中的start_kernel()函数
asmlinkage void __init start_kernel(void)
{
char *command_line;
externstruct kernel_param __start___param[], __stop___param[];
printk(KERN_NOTICE"<lujiado>smp_setup_processor_id->start/n");
smp_setup_processor_id();
// 当只有一个CPU的时候这个函数就什么也不做,所以就把它定义为空,但是如//果有多个CPU的时候那么它就返回在启动的时候的那个CPU的ID,而这个函数//在配置了多CPU的时候是有定义的。
//
printk(KERN_NOTICE"<lujiado>smp_setup_processor_id->end/n");
/*
* Need to run as early as possible, toinitialize the
* lockdep hash:
*/
lockdep_init();
// lockdep_init();
// 定义在include/linux/lockdep.h文件中
// // define lockdep_init() do { } while (0)
// 它是一个宏,什么也不做
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*第四个函数是debug_objects_early_init();
//定义在include/linux/debugobjects.h文件中
//static inline void debug_objects_early_init(void) { }
/// 它是个内联函数,什么也不做
*/
boot_init_stack_canary();
cgroup_init_early();
// cgroup_init_early();
// 它定义在include/linux/cgroup.h
// static inline intcgroup_init_early(void) { return 0; }
// 它是一个内联函数,什么也不做
local_irq_disable();
//它定义在include/asm-alpha/system.h文件中
// #define local_irq_disable() do {setipl(IPL_MAX);barrier(); } while(0)
// 它是一个宏,执行setipl(IPL_MAX);和barrier()函数,其中IPL_MAX为7,//setipl()也是宏,也在该文件中定义,为:#define
// setipl(ipl) ((void)
/// swpipl(ipl)),而barrier()定义在arch/powerpc/boot/io.h文件中,为:
/// static
/// inline void barrier(void)
///
//// {
////
///
//// asm
//// volatile("" : : :"memory");
//// }
//// 用于实现内存屏蔽
early_boot_irqs_off();
/*它定义在文件include/linux/lockdep.h中,为:static
inline void early_boot_irqs_off(void) {}
是一个内联函数,什么也不做*/
early_init_irq_lock_class();
/* 它定义在文件include/linux/lockdep.h中,为:static
inline void early_init_irq_lock_class(void){}
是个内联函数,什么也不做*/
/*
* Interrupts arestill disabled. Do necessary setups, then
* enable them
*/
lock_kernel();
tick_init();
boot_cpu_init();
/*
lock_kernel()定义在文件include/linux/smp_lock.h中,为:
#define lock_kernel() do { } while(0)是个宏,什么也不做
tick_init()定义在文件include/linux/tick.h,为:
staticinline void tick_init(void) { }是个内联函数,什么也不做
boot_cpu_init();定义在文件init/main.c函数中,它定义为:
static
void __init boot_cpu_init(void)
{
int
cpu = smp_processor_id();
/*
Mark the boot cpu "present","online" etc for
SMP and UP case */
cpu_set(cpu,cpu_online_map);
cpu_set(cpu, cpu_present_map);
cpu_set(cpu, cpu_possible_map);
}
它企图激活第一个处理器,其中函数smp_processor_id()定义在include/linux/smp.h文件中,它返回当前CPU
ID,定义为:
#ifdef
CONFIG_DEBUG_PREEMPT
extern unsigned intdebug_smp_processor_id(void);
#
define smp_processor_id() debug_smp_processor_id()
#else
#
define smp_processor_id() raw_smp_processor_id()
#endif
如果DEBUG_PREEMPT使能的话,我们需检查它是否在安全抢占模式下,一般当它使用在非抢占临界区或一个和当前CPU绑定的线程上,它是安全的,ram_smp_processor_id()只在内部使用,它是一个宏定义,为:#define
raw_smp_processor_id() 0
*/
page_address_init();
/*
page_address_init(),它定义在include/linux/mm.h,也是一个宏,实现:#define
page_address_init() do { } while(0),什么也不做
[*]然后是打印语句printk(KERN_NOTICE);其中KERN_NOTICE定义在文件include/linux/kernel.h中,实现如下:
#define
KERN_EMERG "" /* system is unusable
*/
#define
KERN_ALERT "" /* action must be taken
immediately */
#define
KERN_CRIT "" /* critical conditions
*/
#define
KERN_ERR "" /* error conditions
*/
#define
KERN_WARNING "" /* warning conditions
*/
#define
KERN_NOTICE "" /* normal but significant
condition */
#define
KERN_INFO "" /* informational
*/
#define
KERN_DEBUG "" /* debug-level messages
*/
[*]然后打印语句printk(linux_banner);
其中linux_banner定义在init/version.c中,具体定义如下:
/*
FIXED STRINGS! Don't touch! */
const
char linux_banner[] =
"Linux
version " UTS_RELEASE " ("LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST
") (" LINUX_COMPILER ") "UTS_VERSION "/n";
*/
printk(KERN_NOTICE"%s", linux_banner);
setup_arch(&command_line);/*初始化内存*/
//返回内核参数和内核可用的物理地址范围
printk(KERN_NOTICE"init start_kernel()->setup_arch end/n ");
mm_init_owner(&init_mm,&init_task);// //空函数 /include/linux/sched.h /kernel/fork.c 实现
printk(KERN_NOTICE"init start_kernel()->mm_init_owner end/n ");
setup_command_line(command_line);
//保存命令行,以备后用,此保存空间需申请
//这个函数调用完了,就开始执行下面初始化函数
printk(KERN_NOTICE"init start_kernel()->setup_command_line() end/n ");
setup_nr_cpu_ids(); //空函数
setup_per_cpu_areas();//设置每个CPU的信息,单核CPU为空函数
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
//设置启动的CPU为在线状态.在多CPU架构下
//第一个启动的cpu启动到一定阶段后,开始启动其它的cpu,它会为每个后来启动的cpu创建一个0号进程,而这些0号进程的堆栈的thread_info结构中的cpu成员变量则依次被分配出来(利用alloc_cpu_id()函数)并设置好,这样当这些cpu开始运行的时候就有了自己的逻辑cpu号。
build_all_zonelists(NULL);////建立内存区域链表
page_alloc_init();//内存页初始化,此处无执行
printk(KERN_NOTICE"Kernel command line: %s/n", boot_command_line);
parse_early_param();//没有解释
parse_args("Bootingkernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
/*
* These use large bootmem allocations and mustprecede
* kmem_cache_init()
*/
pidhash_init();//进程哈希表初始化
vfs_caches_init_early();//建立节点哈希表和数据缓冲哈希表 sort_main_extable();////对异常处理函数进行排序
trap_init(); //初始化硬件中断 /arch/i386/kernel/traps.c文件里定义此函数
mm_init();
/*
* Set up the scheduler prior starting anyinterrupts (such as the
* timer interrupt). Full topology setuphappens at smp_init()
* time - but meanwhile we still have afunctioning scheduler.
*/
sched_init();//初始化调度/kernel/sched.c文件里有详细的调度算法(这些会
///在以后进程管理和调度的结构分析中详细介绍)
/*
* Disable preemption - early bootup schedulingis extremely
* fragile until we cpu_idle() for the firsttime.
*/
preempt_disable();////启动阶段系统比较脆弱,禁止进程调度
if(!irqs_disabled()) {
printk(KERN_WARNING"start_kernel(): bug: interrupts were "
"enabled*very* early, fixing it/n");
local_irq_disable();
}
rcu_init();//linux2.6的一种互斥访问机制
radix_tree_init();
/* initsome links before init_ISA_irqs() */
early_irq_init();
init_IRQ();//中断向量初始化
prio_tree_init();////初始化优先级数组
init_timers();///定时器初始化
hrtimers_init();///高精度时钟初始化
softirq_init();//软中断初始化
timekeeping_init();////系统时间初始化
time_init();
profile_init();//空函数
if(!irqs_disabled())
printk(KERN_CRIT"start_kernel(): bug: interrupts were "
"enabled early/n");
early_boot_irqs_on();
local_irq_enable();
/*Interrupts are enabled now so all GFP allocations are safe. */
gfp_allowed_mask= __GFP_BITS_MASK;
kmem_cache_init_late();
/*
* HACK ALERT! This is early. We're enablingthe console before
* we've done PCI setups etc, andconsole_init() must be aware of
* this. But we do want output early, in casesomething goes wrong.
*/
console_init();//打印终端初始化
if(panic_later)
panic(panic_later,panic_param);
lockdep_info();
/*
* Need to run this when irqs are enabled,because it wants
* to self-test [hard/soft]-irqs on/off lockinversion bugs
* too:
*/
locking_selftest();
#ifdef CONFIG_BLK_DEV_INITRD
if(initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void*)initrd_start)) < min_low_pfn) {
printk(KERN_CRIT"initrd overwritten (0x%08lx < 0x%08lx) - "
"disabling it./n",
page_to_pfn(virt_to_page((void*)initrd_start)),
min_low_pfn);
initrd_start= 0;
}
#endif
page_cgroup_init();
enable_debug_pagealloc();
kmemtrace_init();
kmemleak_init();
debug_objects_mem_init();
idr_init_cache();//创建idr缓冲区
setup_per_cpu_pageset();//采用的是一致性内存,此函数为空
numa_policy_init();//采用的是一致性内存,此函数为空
if(late_time_init)
late_time_init();
sched_clock_init();
calibrate_delay();//校准延时函数的精确度,实际上是校准loops_per_jiffy全局变量,即每个时钟滴答内CPU执行的指令数
pidmap_init();//进程号位图初始化,一般用一个page来指示所有的进程PID占用情况
anon_vma_init();//空函数
#ifdef CONFIG_X86
if(efi_enabled)
efi_enter_virtual_mode();
#endif
thread_info_cache_init();//空函数
cred_init();
fork_init(totalram_pages);//初始化kernel的fork()环境。Linux下应用程序执行是靠系统调用fork()完成,fork_init所完成的工作就是确定可以fork()的线程的数量,然后是初始化init_task进程
proc_caches_init();//为proc文件系统创建高速缓存 buffer_init();
key_init();();//没有键盘则为空,如果有键盘,则为键盘分配一个高速缓存
security_init();//空函数 dbg_late_init();
vfs_caches_init(totalram_pages);//虚拟文件系统挂载,这个函数的是重点,需要研究一下。
signals_init();////创建并初始化信号队列
/* rootfspopulating might need page-writeback */
page_writeback_init();//CPU在内存中开辟高速缓存,CPU直接访问高速缓存提以高速度。当cpu更新了高速缓存的数据后,需要定期将高速缓存的数据写回到存储介质中,比如磁盘和flash等。这个函数初始化写回的周期
#ifdef CONFIG_PROC_FS
proc_root_init();////如果配置了proc文件系统,则需初始化并加载proc文件系统。在根目录的proc文件夹就是proc文件系统,这个文件系统是ram类型的,记录系统的临时数据,系统关机后不会写回到flash
#endif
cgroup_init();//没有配置cgroup,此函数为空
cpuset_init();//单CPU,此函数为空
taskstats_init_early();//进程状态初始化,实际上就是分配了一个存储线程状态的高速缓存
delayacct_init();//空函数
check_bugs();//空函数
acpi_early_init();/* before LAPIC and SMP init *///空函数
sfi_init_late();
ftrace_init();
/* Do therest non-__init'ed, we're now alive */
rest_init();
}
// 定义在include/linux/lockdep.h文件中
// // define lockdep_init() do { } while (0)
// 它是一个宏,什么也不做
//定义在include/linux/debugobjects.h文件中
//static inline void debug_objects_early_init(void) { }
/// 它是个内联函数,什么也不做
// 它定义在include/linux/cgroup.h
// 它是一个内联函数,什么也不做
// #define local_irq_disable() do {setipl(IPL_MAX);barrier(); } while(0)
// 它是一个宏,执行setipl(IPL_MAX);和barrier()函数,其中IPL_MAX为7,//setipl()也是宏,也在该文件中定义,为:#define
// setipl(ipl) ((void)
/// swpipl(ipl)),而barrier()定义在arch/powerpc/boot/io.h文件中,为:
/// static
/// inline void barrier(void)
///
//// {
////
///
//// asm
//// volatile("" : : :"memory");
//// }
//// 用于实现内存屏蔽
inline void early_boot_irqs_off(void) {}
是一个内联函数,什么也不做*/
inline void early_init_irq_lock_class(void){}
是个内联函数,什么也不做*/
tick_init()定义在文件include/linux/tick.h,为:
boot_cpu_init();定义在文件init/main.c函数中,它定义为:
static
void __init boot_cpu_init(void)
{
int
cpu = smp_processor_id();
/*
Mark the boot cpu "present","online" etc for
SMP and UP case */
cpu_set(cpu,cpu_online_map);
cpu_set(cpu, cpu_present_map);
cpu_set(cpu, cpu_possible_map);
}
它企图激活第一个处理器,其中函数smp_processor_id()定义在include/linux/smp.h文件中,它返回当前CPU
ID,定义为:
#ifdef
CONFIG_DEBUG_PREEMPT
extern unsigned intdebug_smp_processor_id(void);
#
define smp_processor_id() debug_smp_processor_id()
#else
#
define smp_processor_id() raw_smp_processor_id()
#endif
如果DEBUG_PREEMPT使能的话,我们需检查它是否在安全抢占模式下,一般当它使用在非抢占临界区或一个和当前CPU绑定的线程上,它是安全的,ram_smp_processor_id()只在内部使用,它是一个宏定义,为:#define
raw_smp_processor_id() 0
page_address_init() do { } while(0),什么也不做
[*]然后是打印语句printk(KERN_NOTICE);其中KERN_NOTICE定义在文件include/linux/kernel.h中,实现如下:
#define
KERN_EMERG "" /* system is unusable
*/
#define
KERN_ALERT "" /* action must be taken
immediately */
#define
KERN_CRIT "" /* critical conditions
*/
#define
KERN_ERR "" /* error conditions
*/
#define
KERN_WARNING "" /* warning conditions
*/
#define
KERN_NOTICE "" /* normal but significant
condition */
#define
KERN_INFO "" /* informational
*/
#define
KERN_DEBUG "" /* debug-level messages
*/
[*]然后打印语句printk(linux_banner);
其中linux_banner定义在init/version.c中,具体定义如下:
/*
FIXED STRINGS! Don't touch! */
const
char linux_banner[] =
"Linux
version " UTS_RELEASE " ("LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST
") (" LINUX_COMPILER ") "UTS_VERSION "/n";
//返回内核参数和内核可用的物理地址范围
- 基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程二
- 基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程四--device driver 移植---内核初始化优化宏
- 基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程一
- 基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程三
- FL2440 Linux kernel + yaffs2根文件移植过程(二)
- FL2440 Linux kernel + yaffs2根文件移植过程(二)
- 移植Linux 2.6.30.4到mini2440(Kernel)
- 嵌入式 Linux开发Kernel移植(二)——kernel内核配置和编译
- Linux Kernel 2.6.5 内核编译过程
- 把linux kernel 2.4 上的driver 移植到 2.6 kernel
- 移植 kernel linux-2.6.30.4
- Linux内核目录结构(2.6版本以上的kernel)
- arm linux kernel 从入口到start_kernel 的代码分析(2.6内核)
- 编译你自己的Linux内核(Kernel)
- 编译你自己的Linux内核(Kernel)
- 基于S3C2410平台的Linux 2.6.14内核+平台驱动的移植指南(最终版)
- 基于S3C2410平台的Linux 2.6.14内核+平台驱动的移植指南(最终版)
- 移植linux内核到s3c6410(kernel 打印:Uncompressing Linux ... done , booting the kernel.后无响应问题的解决。)
- getopt 妙用
- lucene.net三种检索形式 备忘
- 集线器,交换机,路由器
- javascirpt - 字符串的换行赋值
- test
- 基于PXAxxx平台的Andriod(Linux kernel 2.6.29)内核移植到Meego(linux kernel 2.6.35)过程二
- JAVA3D包功能介绍
- saml安全
- 手动修改spfile.ora文件导致oracle启动不了的解决办法
- 自动程序更新方法一种
- Count the number of 1(MIT hackmem)
- 【转载】SVN备份和还原
- java3d web3d相关网址
- insertion sort