zoukankan      html  css  js  c++  java
  • Linux内核分析第三周学习笔记

    linux内核分析第三周学习笔记

    标签(空格分隔): 20135328陈都


    陈都 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


    构造一个简单的Linux系统MenuOS


    上周回顾:

    • 计算机三大法宝

    • 存储程序计算机

    • 函数调用堆栈

    • 中断

    • 操作系统两把宝剑

    • 中断上下文的切换

    • 进程上下文的切换


    Linux内核源码简介

    我们关注的部分

    • arch/x86目录下的代码
    • init/main.c中start_kernel函数就相当于普通C程序的main函数
    • kernel目录:存放linux内核最核心的代码,用于实现系统的核心模块,包括进程管理、进程调度器、中断处理、系统时钟管理、同步机制等

    README

    提供内核的各种编译方法、生成文件的查看方法。

    • installing 如何安装内核源代码
    • make mrproper 清理安装时生成的中间代码

    启动Linux内核的三个参数:

    • kernel
    • initrd
    • root所在分区、目录

    需要知道的一行代码:qemu -kernel (文件名) -initrd (rootfs.img)

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S


    使用gdb跟踪调试内核

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s
    -S # 关于-s和-S选项的说明:
    -S freeze CPU at startup (use ’c’ to start execution)
    -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb
    tcp:xxxx来取代-s选项

    另开一个shell窗口

    gdb (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
    (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
    (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

    总结分析start_kernel

    start_kernel:包括很多模块的初始化。

    分析内核都会涉及到start_kernel,都会在init初始化。

    详细分析从start_kernel到init进程启动的过程

    start_kernel函数的执行代码在init目录下的main.c[1]

    500asmlinkage __visible void __init start_kernel(void)
    501{
       char *command_line;
       char *after_dashes;
    505    /*
        * Need to run as early as possible, to initialize the
        * lockdep hash:
        */
       lockdep_init();
       set_task_stack_end_magic(&init_task);     init_task即手工创建的PCB,0号进程即最终的idle进程。
       smp_setup_processor_id();
       debug_objects_early_init();
    514    /*
        * Set up the the initial canary ASAP:
        */
       boot_init_stack_canary();
    519    cgroup_init_early();
    521    local_irq_disable();
       early_boot_irqs_disabled = true;
    524/*
    * Interrupts are still disabled. Do necessary setups, then
    * enable them
    */
       boot_cpu_init();
       page_address_init();
       pr_notice("%s", linux_banner);
       setup_arch(&command_line);
       mm_init_cpumask(&init_mm);
       setup_command_line(command_line);
       setup_nr_cpu_ids();
       setup_per_cpu_areas();
       smp_prepare_boot_cpu();    /* arch-specific boot-cpu hooks */
    538    build_all_zonelists(NULL, NULL);
       page_alloc_init();
    541    pr_notice("Kernel command line: %s
    ", boot_command_line);
       parse_early_param();
       after_dashes = parse_args("Booting kernel",
                     static_command_line, __start___param,
                     __stop___param - __start___param,
                     -1, -1, &unknown_bootoption);
       if (!IS_ERR_OR_NULL(after_dashes))
           parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
                  set_init_arg);
    551    jump_label_init();
    553    /*
        * These use large bootmem allocations and must precede
        * kmem_cache_init()
        */
       setup_log_buf(0);
       pidhash_init();
       vfs_caches_init_early();
       sort_main_extable();
       trap_init();   涉及到中断的初始化
       mm_init();
    564    /*
        * Set up the scheduler prior starting any interrupts (such as the
        * timer interrupt). Full topology setup happens at smp_init()
        * time - 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();
       if (WARN(!irqs_disabled(),
            "Interrupts were enabled *very* early, fixing it
    "))
           local_irq_disable();
       idr_init_cache();
       rcu_init();
       context_tracking_init();
       radix_tree_init();
       /* init some links before init_ISA_irqs() */
       early_irq_init();
       init_IRQ();
       tick_init();
       rcu_init_nohz();
       init_timers();
       hrtimers_init();
       softirq_init();
       timekeeping_init();
       time_init();
       sched_clock_postinit();
       perf_event_init();
       profile_init();
       call_function_init();
       WARN(!irqs_disabled(), "Interrupts were enabled early
    ");
       early_boot_irqs_disabled = false;
       local_irq_enable();
    600    kmem_cache_init_late();
    602    /*
        * 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();
       if (panic_later)
           panic("Too many boot %s vars at `%s'", panic_later,
                 panic_param);
    612    lockdep_info();
    614    /*
        * 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();
    621#ifdef CONFIG_BLK_DEV_INITRD
       if (initrd_start && !initrd_below_start_ok &&
           page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
           pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.
    ",
               page_to_pfn(virt_to_page((void *)initrd_start)),
               min_low_pfn);
           initrd_start = 0;
       }
    629#endif
       page_cgroup_init();
       debug_objects_mem_init();
       kmemleak_init();
       setup_per_cpu_pageset();
       numa_policy_init();
       if (late_time_init)
           late_time_init();
       sched_clock_init();
       calibrate_delay();
       pidmap_init();
       anon_vma_init();
       acpi_early_init();
    642#ifdef CONFIG_X86
       if (efi_enabled(EFI_RUNTIME_SERVICES))
           efi_enter_virtual_mode();
    645#endif
    646#ifdef CONFIG_X86_ESPFIX64
       /* Should be run before the first non-init thread is created */
       init_espfix_bsp();
    649#endif
       thread_info_cache_init();
       cred_init();
       fork_init(totalram_pages);
       proc_caches_init();
       buffer_init();
       key_init();
       security_init();
       dbg_late_init();
       vfs_caches_init(totalram_pages);
       signals_init();
       /* rootfs populating might need page-writeback */
       page_writeback_init();
       proc_root_init();
       cgroup_init();
       cpuset_init();
       taskstats_init_early();
       delayacct_init();
    668    check_bugs();
    670    sfi_init_late();
    672    if (efi_enabled(EFI_RUNTIME_SERVICES)) {
           efi_late_init();
           efi_free_boot_services();
       }
    677    ftrace_init();
    679    /* Do the rest non-__init'ed, we're now alive */
       rest_init();
    681}
    
    

    1. -20135301blog ↩︎

  • 相关阅读:
    wordpress通过$wpdb获取一个分类下所有的文章
    WordPress的摘要显示方式
    WordPress简洁的SEO标题、关键词和描述
    WordPress获取特色图像的链接地址
    WordPress的Bootstrap面包屑导航
    destoon 6.0 手机站支持在所有浏览器访问
    dede织梦5.7的安全防护设置
    WordPress主题制作:基础样式文件
    LInux常用到的命令(面试)
    1030 完美数列 (25分) PAT-B
  • 原文地址:https://www.cnblogs.com/cdcode/p/5272802.html
Copyright © 2011-2022 走看看