新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 淺談分析Arm linux 內核移植及系統初始化的過程四

        淺談分析Arm linux 內核移植及系統初始化的過程四

        作者: 時間:2016-11-09 來源:網絡 收藏
        7、淺談分析Arm linux 內核移植系統初始化的過程 咨詢QQ:313807838

        MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
        * to SMDK2410 */
        /* Maintainer: Jonas Dietsche */
        .phys_io = S3C2410_PA_UART,
        .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
        .boot_params = S3C2410_SDRAM_PA + 0x100,
        .map_io = smdk2410_map_io,
        .init_irq = s3c24xx_init_irq,
        .init_machine = smdk_machine_init,
        .timer = &s3c24xx_timer,
        MACHINE_END

        本文引用地址:http://www.104case.com/article/201611/318026.htm

        由此可見在.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_irq, 所以調用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/init/main.c
        do_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 edwin
        machine_name = mdesc->name;

        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 (mdesc->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 = (unsigned long) &_end;

        memcpy(saved_command_line, from, COMMAND_LINE_SIZE);

        8、淺談分析Arm linux 內核移植及系統初始化的過程 咨詢QQ:313807838
        saved_command_line[COMMAND_LINE_SIZE-1] = /0;
        parse_cmdline(cmdline_p, from);
        paging_init(&meminfo, mdesc);
        request_standard_resources(&meminfo, mdesc);

        #ifdef CONFIG_SMP
        smp_init_cpus();
        #endif

        cpu_init();

        /*
        * Set up various architecture-specific 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
        #endif
        }
        5.3. rest_init()函數分析
        下面我們來分析下rest_init()函數。
        Start_kernel() 函數負責初始化內核各子系統,最后調用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 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);
        /*
        * 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_init_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進程

        9、淺談分析Arm linux 內核移植及系統初始化的過程 咨詢QQ:313807838
        */

        if (!ramdisk_execute_command)
        ramdisk_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..
        */
        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)
        printk(KERN_WARNING "Warning: unable to open an initial console./n");

        (void) sys_dup(0);
        (void) sys_dup(0);

        if (ramdisk_execute_command) {
        run_init_process(ramdisk_execute_command);
        printk(KERN_WARNING "Failed to execute %s/n",
        ramdisk_execute_command);
        }

        /*
        * We try each of these until one succeeds.
        *
        * The Bourne shell can be used instead of init if we are
        * trying to recover a really broken machine.
        */
        if (execute_command) {
        run_init_process(execute_command);
        printk(KERN_WARNING "Failed to execute %s. Attempting "
        "defaults.../n", execute_command);
        }
        run_init_process("/sbin/init");
        run_init_process("/etc/init");
        run_init_process("/bin/init");
        run_init_process("/bin/sh");

        panic("No init found. Try passing init= option to kernel.");
        }

        5.3.1. 掛接根文件系統
        Linux/init/ramfs.c
        void __init populate_rootfs(void)
        {
        char *err = unpack_to_rootfs(__initramfs_start,
        __initramfs_end - __initramfs_start, 0);
        if (err)
        panic(err);
        #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start) {
        #ifdef CONFIG_BLK_DEV_RAM
        int fd;
        printk(KERN_INFO "checking if image is initramfs...");
        err = unpack_to_rootfs((char *)initrd_start,
        initrd_end - initrd_start, 1);
        if (!err) {
        printk(" it is/n");
        unpack_to_rootfs((char *)initrd_start,
        initrd_end - initrd_start, 0);
        free_initrd();
        return;
        }
        printk("it isnt (%s); looks like an initrd/n", err);



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 舟曲县| 阳原县| 安义县| 天峨县| 德州市| 凌云县| 乌拉特中旗| 邹城市| 疏勒县| 马公市| 鄂托克前旗| 宣汉县| 临泽县| 噶尔县| 晋宁县| 吴忠市| 策勒县| 保亭| 达州市| 常德市| 荆州市| 桂林市| 灵宝市| 邳州市| 乌鲁木齐市| 疏附县| 新安县| 沈阳市| 西和县| 衢州市| 库尔勒市| 胶州市| 赤水市| 石林| 多伦县| 青川县| 会泽县| 宝坻区| 舒城县| 巴东县| 丽江市|