Armlinux内核移植及系统初始化过程分析

上传人:痛*** 文档编号:123165881 上传时间:2022-07-21 格式:DOC 页数:22 大小:92.50KB
收藏 版权申诉 举报 下载
Armlinux内核移植及系统初始化过程分析_第1页
第1页 / 共22页
Armlinux内核移植及系统初始化过程分析_第2页
第2页 / 共22页
Armlinux内核移植及系统初始化过程分析_第3页
第3页 / 共22页
资源描述:

《Armlinux内核移植及系统初始化过程分析》由会员分享,可在线阅读,更多相关《Armlinux内核移植及系统初始化过程分析(22页珍藏版)》请在装配图网上搜索。

1、Arm linux 内核移植及系统初始化过程分析Edwin. Rong edwinrongmxic 本文主要介绍内核移植过程中涉及文件的分布及其用途,以及简单介绍系统的初始化过程。整个arm linux内核的启动可分为三个阶段:第一阶段主要是进行cpu和体系结构的检查、cpu本身的初始化以及页表的建立等;第二阶段主要是对系统中的一些根底设施进行初始化;最后那么是更高层次的初始化,如根设备和外部设备的初始化。了解系统的初始化过程,有益于更好地移植内核。1. 内核移植涉及文件分布介绍1.1. 内核移植涉及的头文件/linux-2.6.18.8/includerootlocalhost includ

2、e# tree -L 1.|- Kbuild|- acpi|- asm - asm-arm|- asm-alpha|- asm-arm -(1)|- asm-sparc|- asm-sparc64|- config|- keys|- linux-(2)|- math-emu|- media|- mtd|- net|- pcmcia|- rdma|- rxrpc|- scsi|- sound- video内核移植过程中涉及到的头文件包括处理器相关的头文件(1)和处理器无关的头文件(2)。1.2. 内核移植涉及的源文件/linux-2.6.18.8/arch/armrootlocalhost ar

3、m# tree -L 1.|- Kconfig|- Kconfig-nommu|- Kconfig.debug|- Makefile|- boot -(2)|- common|- configs|- kernel -(3)|- lib|- mach-at91rm9200|- mach-omap1|- mach-omap2|- mach-realview|- mach-rpc|- mach-s3c2410 -(4)|- mach-sa1100|- mach-versatile|- mm -(5)|- nwfpe|- oprofile|- plat-omap|- tools -(1)- vfp(1

4、)/linux-2.6.18.8/arch/arm/toolsrootlocalhost tools# tree -L 1.|- Makefile|- gen-mach-types- mach-typesMach-types 文件定义了不同系统平台的系统平台号。移植linux内核到新的平台上需要对新的平台登记系统平台号。Mach-types文件格式如下:# machine_is_xxxCONFIG_xxxxMACH_TYPE_xxxnumbers3c2410ARCH_S3C2410S3C2410 182smdk2410ARCH_SMDK2410SMDK2410 193之所以需要这些信息,是因为

5、脚本文件linux/arch/arm/tools/gen-mach-types需要linux/arch/tools/mach-types来产生linux/include/asm-arm/mach-types.h文件,该文件中设置了一些宏定义,需要这些宏定义来为目标系统选择适宜的代码。(2)linux-2.6.18.8/arch/arm/boot/compressedrootlocalhost compressed# tree -L 1.|- Makefile|- Makefile.debug|- big-endian.S|- head-at91rm9200.S|- head.S|- ll_ch

6、ar_wr.S|- misc.c|- ofw-shark.c|- piggy.S- vmlinux.lds.inHead.s 是内核映像的入口代码,是自引导程序。自引导程序包含一些初始化程序,这些程序都是体系结构相关的。在对系统作完初始化设置工作后,调用misc.c文件中的decompress_kernel()函数解压缩内核映像到指定的位置,然后跳转到kernel的入口地址。Vmlinux.lds.in用来生成内核映像的内存配置文件。(3)linux-2.6.18.8/arch/arm/kernelrootlocalhost kernel# tree -L 1.|- Makefile|- ap

7、m.c|- armksyms.c|- arthur.c|- asm-offsets.c|- bios32.c|- calls.S|- dma.c|- ecard.c|- entry-armv.S|- entry-common.S|- entry-header.S|- fiq.c|- head-common.S|- head-nommu.S|- head.S|- init_task.c|- io.c|- irq.c|- isa.c|- module.c|- process.c|- ptrace.c|- ptrace.h|- semaphore.c|- setup.c|- smp.c|- sys_

8、arm.c|- time.c|- traps.c- vmlinux.lds.S内核入口处也是由一段汇编语言实现的,由head.s和head-common.s两个文件组成。Head.s 是内核的入口文件, 在head.s的末尾处 #include head-common.S。 经过一系列的初始化后,跳转到linux-2.6.18.8/init/main.c中的start_kernel()函数中,开始内核的根本初始化过程。/linux-2.6.18.8/initrootlocalhost init# tree.|- Kconfig|- Makefile|- calibrate.c|- do_mou

9、nts.c|- do_mounts.h|- do_mounts_initrd.c|- do_mounts_md.c|- do_mounts_rd.c|- initramfs.c|- main.c- version.c(4)/linux-2.6.18.8/arch/arm/mach-s3c2410rootlocalhost mach-s3c2410# tree -L 1.|- Kconfig|- Makefile|- Makefile.boot|- bast-irq.c|- bast.h|- clock.c|- clock.h|- common-smdk.c|- common-smdk.h|-

10、cpu.c|- cpu.h|- devs.c|- devs.h|- dma.c|- gpio.c|- irq.c|- irq.h|- mach-anubis.c|- mach-smdk2410.c|- pm-simtec.c|- pm.c|- pm.h|- s3c2400-gpio.c|- s3c2400.h|- s3c2410-clock.c|- s3c2410-gpio.c|- s3c2410.c|- s3c2410.h|- sleep.S|- time.c|- usb-simtec.c- usb-simtec.h这个目录中的文件都是板级相关的,其中比拟重要是如下几个:linux/arch

11、/arm/mach-s3c2410/cpu.c linux/arch/arm/mach-s3c2410/common-smdk.clinux/arch/arm/mach-s3c2410/devs.clinux/arch/arm/mach-s3c2410/mach-smdk2410.clinux/arch/arm/mach-s3c2410/Makefile.bootlinux/arch/arm/mach-s3c2410/s3c2410.c2. 处理器和设备这里主要介绍处理器和设备的描述和操作过程。设备描述在linux/arch/arm/mach-s3c2410/devs.c和linux/arch

12、/arm/mach-s3c2410/common-smdk.c中实现。最后以nand flash为例具体介绍。2.1. 处理器、设备描述设备描述主要两个结构体完成:struct resource和struct platform_device。先来看看着两个结构体的定义:struct resource resource_size_t start;resource_size_t end;const char *name;unsigned long flags;struct resource *parent, *sibling, *child;Resource结构体主要是描述了设备在系统中的起止地址

13、、名称、标志以及为了链式描述方便指向本结构体类型的指针。Resource定义的实例将被添加到platform_device结构体对象中去。struct platform_device const char* name;u32id;struct devicedev;u32num_resources;struct resource* resource;Platform_device结构体包括结构体的名称、ID号、平台相关的信息、设备的数目以及上面定义的resource信息。Platform_device结构对象将被直接通过设备操作函数注册导系统中去。具体注册和注销过程在下一节介绍。2.2. 处理器

14、、设备操作(1) int platform_device_register(struct platform_device * pdev); 注册设备(2) void platform_device_unregister(struct platform_device * pdev); 注销设备(3) int platform_add_devices(struct platform_device *devs, int num);添加设备,通过调用上面两个函数实现。2.3. 添加Nand flash设备下面以nand flash 设备的描述为例,具体介绍下设备的描述和注册过程。/ resource结

15、构体实例s3c_nand_resource 对nand flash 控制器描述,包括控制器的起止地址和标志。static struct resource s3c_nand_resource = 0 = .start = S3C2410_PA_NAND,.end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,.flags = IORESOURCE_MEM,;/platform_device结构体实例s3c_device_nand定义了设备的名称、ID号并把resource对象作为其成员之一。struct platform_device s3c_device_na

16、nd = .name = s3c2410-nand,.id = -1,.num_resources = ARRAY_SIZE(s3c_nand_resource),.resource = s3c_nand_resource,;/ nand flash 的分区情况,由mtd_partition结构体定义。static struct mtd_partition smdk_default_nand_part = 0 = .name= Boot Agent,.size= SZ_16K,.offset= 0,1 = .name= S3C2410 flash partition 1,.offset = 0

17、,.size= SZ_2M,2 = .name= S3C2410 flash partition 2,.offset = SZ_4M,.size= SZ_4M,3 = .name= S3C2410 flash partition 3,.offset= SZ_8M,.size= SZ_2M,4 = .name= S3C2410 flash partition 4,.offset = SZ_1M * 10,.size= SZ_4M,5 = .name= S3C2410 flash partition 5,.offset= SZ_1M * 14,.size= SZ_1M * 10,6 = .name

18、= S3C2410 flash partition 6,.offset= SZ_1M * 24,.size= SZ_1M * 24,7 = .name= S3C2410 flash partition 7,.offset = SZ_1M * 48,.size= SZ_16M,;static struct s3c2410_nand_set smdk_nand_sets = 0 = .name= NAND,.nr_chips= 1,.nr_partitions= ARRAY_SIZE(smdk_default_nand_part),.partitions= smdk_default_nand_pa

19、rt,;/* choose a set of timings which should suit most 512Mbit * chips and beyond.*/static struct s3c2410_platform_nand smdk_nand_info = .tacls= 20,.twrph0= 60,.twrph1= 20,.nr_sets= ARRAY_SIZE(smdk_nand_sets),.sets= smdk_nand_sets,;/* devices we initialise */ 最后将nand flash 设备参加到系统即将注册的设备集合中。 static s

20、truct platform_device _initdata *smdk_devs = &s3c_device_nand,&smdk_led4,&smdk_led5,&smdk_led6,&smdk_led7,;然后通过smdk_machine_init()函数,调用设备添加函数platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs) 完成设备的注册。具体过程参见系统初始化的相关局部。3. 系统初始化3.1. 系统初始化的主干线Start_kernel() setup_arch() reset_init() kernel_thread(ini

21、t ) init() do_basic_setup() driver_init() do_initcall()Start_kernel()函数负责初始化内核各个子系统,最后调用reset_init(),启动一个叫做init的内核线程,继续初始化。Start_kernel()函数在init/main.c中实现。asmlinkage void _init start_kernel(void)char * command_line;extern struct kernel_param _start_param, _stop_param;smp_setup_processor_id();/* * Ne

22、ed to run as early as possible, to initialize the * lockdep hash: */lockdep_init();local_irq_disable();early_boot_irqs_off();early_init_irq_lock_class();/* * Interrupts are still disabled. Do necessary setups, then * enable them */lock_kernel();boot_cpu_init();page_address_init();printk(KERN_NOTICE)

23、;printk(linux_banner);setup_arch(&command_line); /setup processor and machine and destinate some pointers for do_initcalls() functions / for example init_machine pointer is initialized with smdk_machine_init() function , and /init_machine() function is called by customize_machine(), and the function

24、 is processed by /arch_initcall(fn). Therefore smdk_machine_init() is issured. by edwinsetup_per_cpu_areas();smp_prepare_boot_cpu();/* arch-specific boot-cpu hooks */* * Set up the scheduler prior starting any interrupts (such as the * timer interrupt). Full topology setup happens at smp_init() * ti

25、me - but meanwhile we still have a functioning scheduler. */sched_init();/* * Disable preemption - early bootup scheduling is extremely * fragile until we cpu_idle() for the first time. */preempt_disable();build_all_zonelists();page_alloc_init();printk(KERN_NOTICE Kernel command line: %sn, saved_com

26、mand_line);parse_early_param();parse_args(Booting kernel, command_line, _start_param, _stop_param - _start_param, &unknown_bootoption);sort_main_extable();unwind_init();trap_init();rcu_init();init_IRQ();pidhash_init();init_timers();hrtimers_init();softirq_init();timekeeping_init();time_init();profil

27、e_init();if (!irqs_disabled()printk(start_kernel(): bug: interrupts were enabled earlyn);early_boot_irqs_on();local_irq_enable();/* * HACK ALERT! This is early. Were enabling the console before * weve done PCI setups etc, and console_init() must be aware of * this. But we do want output early, in ca

28、se something 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 lock inversion bugs * too: */locking_selftest();#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start & !

29、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 18) & 0xfffc,.boot_params= S3C2410_SDRAM_PA + 0x100,.map_io= smdk2410_map_io,.init_irq= s3c24xx_init_irq,.init_machine= smdk_machine_init,.timer

30、= &s3c24xx_timer,MACHINE_END由此可见在.arch.info.init段内存放了_desc_mach_desc_SMDK2410结构体。初始化了相应的初始化函数指针。问题又来了, 这些初始化指针函数是什么时候被调用的呢?分析发现,不一而同。如s3c24xx_init_irq()函数是通过start_kernel()里的init_IRQ()函数调用init_arch_irq()实现的。因为在MACHINE_START结构体中 .init_irq= s3c24xx_init_irq,而在setup_arch()函数中init_arch_irq = mdesc-init_i

31、rq, 所以调用init_arch_irq()就相当于调用了s3c24xx_init_irq()。又如smdk_machine_init()函数的初始化。在MACHINE_START结构体中,函数指针赋值,.init_machine= smdk_machine_init。而init_machine()函数被linux/arch/arm/kernel/setup.c文件中的customize_machine()函数调用并被arch_initcall(Fn)宏处理,arch_initcall(customize_machine)。 被arch_initcall(Fn)宏处理过函数将linux/in

32、it/main.cdo_initcalls()函数调用。 具体参看下边的局部。void _init setup_arch(char *cmdline_p)struct tag *tags = (struct tag *)&init_tags;struct machine_desc *mdesc;char *from = default_command_line;setup_processor();mdesc = setup_machine(machine_arch_type);/machine_arch_type =SMDK2410 by edwinmachine_name = mdesc-n

33、ame;if (mdesc-soft_reboot)reboot_setup(s);if (mdesc-boot_params)tags = phys_to_virt(mdesc-boot_params);/* * If we have the old style parameters, convert them to * a tag list. */if (tags-hdr.tag != ATAG_CORE)convert_to_tag_list(tags);if (tags-hdr.tag != ATAG_CORE)tags = (struct tag *)&init_tags;if (m

34、desc-fixup)mdesc-fixup(mdesc, tags, &from, &meminfo);if (tags-hdr.tag = ATAG_CORE) if (meminfo.nr_banks != 0)squash_mem_tags(tags);parse_tags(tags);init_mm.start_code = (unsigned long) &_text;init_mm.end_code = (unsigned long) &_etext;init_mm.end_data = (unsigned long) &_edata;init_mm.brk = (unsigne

35、d long) &_end;memcpy(saved_command_line, from, COMMAND_LINE_SIZE);saved_command_lineCOMMAND_LINE_SIZE-1 = 0;parse_cmdline(cmdline_p, from);paging_init(&meminfo, mdesc);request_standard_resources(&meminfo, mdesc);#ifdef CONFIG_SMPsmp_init_cpus();#endifcpu_init();/* * Set up various architecture-speci

36、fic pointers */init_arch_irq = mdesc-init_irq;system_timer = mdesc-timer;init_machine = mdesc-init_machine;#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)conswitchp = &dummy_con;#endif#endif3.3. rest_init()函数分析下面我们来分析下rest_init()函数。Start_kerne

37、l()函数负责初始化内核各子系统,最后调用reset_init(),启动一个叫做init的内核线程,继续初始化。在init内核线程中,将执行以下init()函数的程序。Init()函数负责完成根文件系统的挂接、初始化设备驱动程序和启动用户空间的init进程等重要工作。static void noinline rest_init(void)_releases(kernel_lock)kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);numa_default_policy();unlock_kernel();/* * The boot idle

38、 thread must execute schedule() * at least one to get things moving: */preempt_enable_no_resched();schedule();preempt_disable();/* Call into cpu_idle with preempt disabled */cpu_idle();static int init(void * unused)lock_kernel();/* * init can run on any cpu. */set_cpus_allowed(current, CPU_MASK_ALL)

39、;/* * Tell the world that were going to be the grim * reaper of innocent orphaned children. * * We dont want people to have to make incorrect * assumptions about where in the task array this * can be found. */child_reaper = current;smp_prepare_cpus(max_cpus);do_pre_smp_initcalls();smp_init();sched_i

40、nit_smp();cpuset_init_smp();/* * Do this before initcalls, because some drivers want to access * firmware files. */populate_rootfs(); /挂接根文件系统do_basic_setup(); /初始化设备驱动程序/* * check if there is an early userspace init. If yes, let it do all * the work /启动用户空间的init进程 */if (!ramdisk_execute_command)ram

41、disk_execute_command = /init;if (sys_access(const char _user *) ramdisk_execute_command, 0) != 0) ramdisk_execute_command = NULL;prepare_namespace();/* * Ok, we have completed the initial bootup, and * were essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.

42、*/free_initmem();unlock_kernel();mark_rodata_ro();system_state = SYSTEM_RUNNING;numa_default_policy();if (sys_open(const char _user *) /dev/console, O_RDWR, 0) = 0) sys_write(fd, (char *)initrd_start,initrd_end - initrd_start);sys_close(fd);free_initrd();#elseprintk(KERN_INFO Unpacking initramfs.);e

43、rr = unpack_to_rootfs(char *)initrd_start,initrd_end - initrd_start, 0);if (err)panic(err);printk( donen);free_initrd();#endif#endif3.3.2. 初始化设备驱动程序linux/init/main.cstatic void _init do_basic_setup(void)/* drivers will send hotplug events */init_workqueues();usermodehelper_init();driver_init(); /* 初

44、始化驱动程序模型。调用驱动初始化函数初始化子系统。 */#ifdef CONFIG_SYSCTLsysctl_init();#endifdo_initcalls();linux/init/main.cextern initcall_t _initcall_start, _initcall_end;static void _init do_initcalls(void)initcall_t *call;int count = preempt_count();for (call = _initcall_start; call _initcall_end; call+) char *msg = NULL;char msgbuf40;int result;if (initcall_debug) printk(Calling initcall 0x%p, *call);print_fn_descriptor_symbol(: %s(),(unsigned long) *call);printk(n);result = (*call)();/* Make sure there is no pending stuff from the initcall sequence */flush_scheduled_work();分析上面一段代码可以看出,设备的初始化是通过do_b

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!