From ca05a579d6c803b23591c96e9f7c49f1605d00f8 Mon Sep 17 00:00:00 2001 From: gatieme Date: Fri, 12 Aug 2016 17:03:33 +0800 Subject: [PATCH] ... --- .../02-memory/03-initialize/start_kernel.c | 185 ------------------ .../04-buddy/01-buddy_system/README.md | 82 ++++++++ .../02-fragmentation}/README.md | 0 .../03-initialization}/README.md | 0 .../03-initialization => 04-buddy}/README.md | 0 .../02-memory/04-phymemmanage/README.md | 46 ----- 6 files changed, 82 insertions(+), 231 deletions(-) delete mode 100644 study/kernel/02-memory/03-initialize/start_kernel.c create mode 100644 study/kernel/02-memory/04-buddy/01-buddy_system/README.md rename study/kernel/02-memory/{04-phymemmanage/01-buddy_system => 04-buddy/02-fragmentation}/README.md (100%) rename study/kernel/02-memory/{04-phymemmanage/02-fragmentation => 04-buddy/03-initialization}/README.md (100%) rename study/kernel/02-memory/{04-phymemmanage/03-initialization => 04-buddy}/README.md (100%) delete mode 100644 study/kernel/02-memory/04-phymemmanage/README.md diff --git a/study/kernel/02-memory/03-initialize/start_kernel.c b/study/kernel/02-memory/03-initialize/start_kernel.c deleted file mode 100644 index f2f04b3..0000000 --- a/study/kernel/02-memory/03-initialize/start_kernel.c +++ /dev/null @@ -1,185 +0,0 @@ -asmlinkage __visible void __init start_kernel(void) -{ - char *command_line; - char *after_dashes; - - set_task_stack_end_magic(&init_task); - smp_setup_processor_id(); - debug_objects_early_init(); - - /* - * Set up the the initial canary ASAP: - */ - boot_init_stack_canary(); - - cgroup_init_early(); - - local_irq_disable(); - early_boot_irqs_disabled = true; - -/* - * 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(); - boot_cpu_state_init(); - smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ - - build_all_zonelists(NULL, NULL); - page_alloc_init(); - - pr_notice("Kernel command line: %s\n", boot_command_line); - parse_early_param(); - after_dashes = parse_args("Booting kernel", - static_command_line, __start___param, - __stop___param - __start___param, - -1, -1, NULL, &unknown_bootoption); - if (!IS_ERR_OR_NULL(after_dashes)) - parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, - NULL, set_init_arg); - - jump_label_init(); - - /* - * 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(); - - /* - * 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\n")) - local_irq_disable(); - idr_init_cache(); - rcu_init(); - - /* trace_printk() and trace points may be used after this */ - trace_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(); - printk_nmi_init(); - perf_event_init(); - profile_init(); - call_function_init(); - WARN(!irqs_disabled(), "Interrupts were enabled early\n"); - early_boot_irqs_disabled = false; - local_irq_enable(); - - kmem_cache_init_late(); - - /* - * 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); - - 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_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.\n", - page_to_pfn(virt_to_page((void *)initrd_start)), - min_low_pfn); - initrd_start = 0; - } -#endif - page_ext_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(); -#ifdef CONFIG_X86 - if (efi_enabled(EFI_RUNTIME_SERVICES)) - efi_enter_virtual_mode(); -#endif -#ifdef CONFIG_X86_ESPFIX64 - /* Should be run before the first non-init thread is created */ - init_espfix_bsp(); -#endif - thread_stack_cache_init(); - cred_init(); - fork_init(); - proc_caches_init(); - buffer_init(); - key_init(); - security_init(); - dbg_late_init(); - vfs_caches_init(); - signals_init(); - /* rootfs populating might need page-writeback */ - page_writeback_init(); - proc_root_init(); - nsfs_init(); - cpuset_init(); - cgroup_init(); - taskstats_init_early(); - delayacct_init(); - - check_bugs(); - - acpi_subsystem_init(); - sfi_init_late(); - - if (efi_enabled(EFI_RUNTIME_SERVICES)) { - efi_late_init(); - efi_free_boot_services(); - } - - ftrace_init(); - - /* Do the rest non-__init'ed, we're now alive */ - rest_init(); -} \ No newline at end of file diff --git a/study/kernel/02-memory/04-buddy/01-buddy_system/README.md b/study/kernel/02-memory/04-buddy/01-buddy_system/README.md new file mode 100644 index 0000000..38c6b1d --- /dev/null +++ b/study/kernel/02-memory/04-buddy/01-buddy_system/README.md @@ -0,0 +1,82 @@ +服务器体系与共享存储器架构 +======= + +| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | +| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| +| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | + + + + +在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. + + + +#2 伙伴系统的结构 +------- + + +系统内存中的每个物理内存页(页帧),都对应于一个struct page实例, 每个内存域都关联了一个struct zone的实例,其中保存了用于管理伙伴数据的主要数数组 + + +```cpp +// http://lxr.free-electrons.com/source/include/linux/mmzone.h?v=4.7#L324 +struct zone +{ + /* free areas of different sizes */ + struct free_area free_area[MAX_ORDER]; +}; +``` + +struct free_area是一个辅助数据结构, 它定义在[include/linux/mmzone.h?v=4.7, line 88](http://lxr.free-electrons.com/source/include/linux/mmzone.h?v=4.7#L88) + +```cpp +struct free_area { + struct list_head free_list[MIGRATE_TYPES]; +unsigned long nr_free; +}; +``` + +| 字段 | 描述 | +|:-----:|:-----:| +| free_list | 是用于连接空闲页的链表. 页链表包含大小相同的连续内存区 | +| nr_free | 指定了当前内存区中空闲页块的数目(对0阶内存区逐页计算,对1阶内存区计算页对的数目,对2阶内存区计算4页集合的数目,依次类推 | + + +阶是伙伴系统中一个非常重要的术语. 它描述了内存分配的数量单位. 内存块的长度是2order,其中order的范围从0到MAX_ORDER, 参见[include/linux/mmzone.h?v=4.7, line 22](http://lxr.free-electrons.com/source/include/linux/mmzone.h?v=4.7#L22) + +```cpp +/* Free memory management - zoned buddy allocator. */ +#ifndef CONFIG_FORCE_MAX_ZONEORDER +#define MAX_ORDER 11 +#else +#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER +#endif +#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1)) +``` + + +该常数通常设置为11,这意味着一次分配可以请求的页数最大是2^11=2048 + +但如果特定于体系结构的代码设置了FORCE_MAX_ZONEORDER配置选项, 该值也可以手工改变 + +例如,IA-64系统上巨大的地址空间可以处理`MAX_ORDER = 18`的情形,而ARM或v850系统则使用更小的值(如8或9). 但这不一定是由计算机支持的内存数量比较小引起的,也可能是内存对齐方式的要求所导致 + +或者可以参考arm体系结构的Kconfig配置文件的描述 + +```cpp +config FORCE_MAX_ZONEORDER +int +default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE) +default "12" if (ARM64_16K_PAGES && TRANSPARENT_HUGEPAGE) +default "11"` +``` + +free_area[]数组中各个元素的索引也解释为阶,用于指定对应链表中的连续内存区包含多少个 +页帧。第0个链表包含的内存区为单页(20=1),第1个链表管理的内存区为两页(21=2),第3个管理 +的内存区为4页,依次类推。 +内存区是如何连接的?内存区中第1页内的链表元素,可用于将内存区维持在链表中。因此,也 +不必引入新的数据结构来管理物理上连续的页,否则这些页不可能在同一内存区中. + +图3-22对此给出 +了图示。 \ No newline at end of file diff --git a/study/kernel/02-memory/04-phymemmanage/01-buddy_system/README.md b/study/kernel/02-memory/04-buddy/02-fragmentation/README.md similarity index 100% rename from study/kernel/02-memory/04-phymemmanage/01-buddy_system/README.md rename to study/kernel/02-memory/04-buddy/02-fragmentation/README.md diff --git a/study/kernel/02-memory/04-phymemmanage/02-fragmentation/README.md b/study/kernel/02-memory/04-buddy/03-initialization/README.md similarity index 100% rename from study/kernel/02-memory/04-phymemmanage/02-fragmentation/README.md rename to study/kernel/02-memory/04-buddy/03-initialization/README.md diff --git a/study/kernel/02-memory/04-phymemmanage/03-initialization/README.md b/study/kernel/02-memory/04-buddy/README.md similarity index 100% rename from study/kernel/02-memory/04-phymemmanage/03-initialization/README.md rename to study/kernel/02-memory/04-buddy/README.md diff --git a/study/kernel/02-memory/04-phymemmanage/README.md b/study/kernel/02-memory/04-phymemmanage/README.md deleted file mode 100644 index 1a3d0ec..0000000 --- a/study/kernel/02-memory/04-phymemmanage/README.md +++ /dev/null @@ -1,46 +0,0 @@ -服务器体系与共享存储器架构 -======= - -| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | -| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| -| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | - - -#1 目录 -------- - -| CSDN | GitHub | -|:-------:|:-------:| -| 描述物理内存 | -| 页表管理 | -| 初始化内存挂历 | -| 物理内存的管理 | -| slab分配器 | - -| 非连续内存分配 | -| 高端内存管理 | -| 页面帧回收 | -| 交换管理 | -| 进程虚拟地址空间 | -| 共享内存虚拟文件系统 | -| 内存溢出管理 | - - -#2 参考内容 -------- - -| 链接 | -|:-------:| -| [内存管理(一)内存模型之Node](http://biancheng.dnbcw.info/linux/387391.html) | -| [Linux 内存管理 重要结构体](http://blog.chinaunix.net/uid-26009500-id-3078986.html) | -| [Bootmem机制](http://blog.csdn.net/samssm/article/details/25064897) | -| [Linux-2.6.32 NUMA架构之内存和调度](http://www.cnblogs.com/zhenjing/archive/2012/03/21/linux_numa.html) | -| [Linux 用户空间与内核空间——高端内存详解](http://blog.csdn.net/tommy_wxie/article/details/17122923) | -| [探索 Linux 内存模型](http://www.ibm.com/developerworks/cn/linux/l-memmod/) | -| [Linux内存管理](http://blog.chinaunix.net/uid/21718047/cid-151509-list-2.html) | -| [内存管理-之内核内存管理-基于linux3.10](http://blog.csdn.net/shichaog/article/details/45509917) | -| [内存管理(一)](http://www.cnblogs.com/openix/p/3334026.html) | -| [Linux内存管理原理](http://www.cnblogs.com/zhaoyl/p/3695517.html) | -| [第 15 章 内存映射和 DMA](http://www.embeddedlinux.org.cn/ldd3/ch15.html) | -| [ 内存管理(二)struct page ](http://blog.chinaunix.net/uid-30282771-id-5176971.html) | -