linux内核smp启动分析,Linux内核启动分析

Linux内核启动代码由位于init/main.cinit/main.c的start_kernel开始,下面对start_kernel进行分析,start_kernel代码如下

asmlinkage __visible void __init start_kernel(void)

501 {

502 char *command_line;

503 char *after_dashes;

504

505 /*

506 * Need to run as early as possible, to initialize the

507 * lockdep hash:

508 */

509 lockdep_init();

510 set_task_stack_end_magic(&init_task);

511 smp_setup_processor_id();

512 debug_objects_early_init();

513

514 /*

515 * Set up the the initial canary ASAP:

516 */

517 boot_init_stack_canary();

518

519 cgroup_init_early();

520

521 local_irq_disable();

522 early_boot_irqs_disabled = true;

523

524 /*

525 * Interrupts are still disabled. Do necessary setups, then

526 * enable them

527 */

528 boot_cpu_init();

529 page_address_init();

530 pr_notice("%s", linux_banner);

531 setup_arch(&command_line);

532 mm_init_cpumask(&init_mm);

533 setup_command_line(command_line);

534 setup_nr_cpu_ids();

535 setup_per_cpu_areas();

536 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */

537

538 build_all_zonelists(NULL, NULL);

539 page_alloc_init();

540

541 pr_notice("Kernel command line: %s\n", boot_command_line);

542 parse_early_param();

543 after_dashes = parse_args("Booting kernel",

544 static_command_line, __start___param,

545 __stop___param - __start___param,

546 -1, -1, &unknown_bootoption);

547 if (!IS_ERR_OR_NULL(after_dashes))

548 parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,

549 set_init_arg);

550

551 jump_label_init();

552

553 /*

554 * These use large bootmem allocations and must precede

555 * kmem_cache_init()

556 */

557 setup_log_buf(0);

558 pidhash_init();

559 vfs_caches_init_early();

560 sort_main_extable();

561 trap_init();//陷入门初始化,系统调用初始化

562 mm_init();//内存管理单元初始化

563

564 /*

565 * Set up the scheduler prior starting any interrupts (such as the

566 * timer interrupt). Full topology setup happens at smp_init()

567 * time - but meanwhile we still have a functioning scheduler.

568 */

569 sched_init();//调度初始化

570 /*

571 * Disable preemption - early bootup scheduling is extremely

572 * fragile until we cpu_idle() for the first time.

573 */

574 preempt_disable();

575 if (WARN(!irqs_disabled(),

576 "Interrupts were enabled *very* early, fixing it\n"))

577 local_irq_disable();

578 idr_init_cache();

579 rcu_init();

580 context_tracking_init();

581 radix_tree_init();

582 /* init some links before init_ISA_irqs() */

583 early_irq_init();

584 init_IRQ();

585 tick_init();

586 rcu_init_nohz();

587 init_timers();

588 hrtimers_init();

589 softirq_init();

590 timekeeping_init();

591 time_init();

592 sched_clock_postinit();

593 perf_event_init();

594 profile_init();

595 call_function_init();

596 WARN(!irqs_disabled(), "Interrupts were enabled early\n");

597 early_boot_irqs_disabled = false;

598 local_irq_enable();

599

600 kmem_cache_init_late();

601

602 /*

603 * HACK ALERT! This is early. We're enabling the console before

604 * we've done PCI setups etc, and console_init() must be aware of

605 * this. But we do want output early, in case something goes wrong.

606 */

607 console_init();//控制台初始化

608 if (panic_later)

609 panic("Too many boot %s vars at `%s'", panic_later,

610 panic_param);

611

612 lockdep_info();

613

614 /*

615 * Need to run this when irqs are enabled, because it wants

616 * to self-test [hard/soft]-irqs on/off lock inversion bugs

617 * too:

618 */

619 locking_selftest();

620

621 #ifdef CONFIG_BLK_DEV_INITRD

622 if (initrd_start && !initrd_below_start_ok &&

623 page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {

624 pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",

625 page_to_pfn(virt_to_page((void *)initrd_start)),

626 min_low_pfn);

627 initrd_start = 0;

628 }

629 #endif

630 page_cgroup_init();

631 debug_objects_mem_init();

632 kmemleak_init();

633 setup_per_cpu_pageset();

634 numa_policy_init();

635 if (late_time_init)

636 late_time_init();

637 sched_clock_init();

638 calibrate_delay();

639 pidmap_init();

640 anon_vma_init();

641 acpi_early_init();

642 #ifdef CONFIG_X86

643 if (efi_enabled(EFI_RUNTIME_SERVICES))

644 efi_enter_virtual_mode();

645 #endif

646 #ifdef CONFIG_X86_ESPFIX64

647 /* Should be run before the first non-init thread is created */

648 init_espfix_bsp();

649 #endif

650 thread_info_cache_init();

651 cred_init();

652 fork_init(totalram_pages);

653 proc_caches_init();

654 buffer_init();

655 key_init();

656 security_init();

657 dbg_late_init();

658 vfs_caches_init(totalram_pages);

659 signals_init();

660 /* rootfs populating might need page-writeback */

661 page_writeback_init();

662 proc_root_init();

663 cgroup_init();

664 cpuset_init();

665 taskstats_init_early();

666 delayacct_init();

667

668 check_bugs();

669

670 sfi_init_late();

671

672 if (efi_enabled(EFI_RUNTIME_SERVICES)) {

673 efi_late_init();

674 efi_free_boot_services();

675 }

676

677 ftrace_init();

678

679 /* Do the rest non-__init'ed, we're now alive */

680 rest_init();//这个比较有意思,下文详细分析

681 }

start_kernel主要进行了各种初始化,对于我们比较敢兴趣的是

561 trap_init();//陷入门初始化,系统调用初始化

562 mm_init();//内存管理单元初始化

569         sched_init();//调度初始化
607         console_init();//控制台初始化
680         rest_init();//这个比较有意思,下文详细分析

rest_init()源代码如下,分析详见注释

static noinline void __init_refok rest_init(void)

394 {

395 int pid;

396

397 rcu_scheduler_starting();

398 /*

399 * We need to spawn init first so that it obtains pid 1, however

400 * the init task will end up wanting to create kthreads, which, if

401 * we schedule it before we create kthreadd, will OOPS.

402 */

403 kernel_thread(kernel_init, NULL, CLONE_FS);//创建了1号进程

404 numa_default_policy();

405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

406 rcu_read_lock();

407 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);

408 rcu_read_unlock();

409 complete(&kthreadd_done);

410

411 /*

412 * The boot idle thread must execute schedule()

413 * at least once to get things moving:

414 */

415 init_idle_bootup_task(current);//初始化0号进程,即系统的idle进程

416 schedule_preempt_disabled();

417 /* Call into cpu_idle with preempt disabled */

418 cpu_startup_entry(CPUHP_ONLINE);

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值