mm_init分析(Zoned Buddy Allocator)

本文分析了Linux内核启动过程中的关键函数start_kernel。该函数负责完成处理器架构初始化、内存管理初始化等工作,并涉及页框管理、物理内存释放等核心操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1 mm_init分析

file:init/main.c

start_kernel函数

{

 ...

 setup_arch(&command_line);

//处理器相关的初始化代码,paging_init,详细见bootmem_init分析
 mm_init_owner(&init_mm, &init_task);
 setup_command_line(command_line);
 setup_nr_cpu_ids();
 setup_per_cpu_areas();
 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */

 build_all_zonelists(NULL);
 page_alloc_init();

 printk(KERN_NOTICE "Kernel command line: %s/n", boot_command_line);
 parse_early_param();
 parse_args("Booting kernel", static_command_line, __start___param,
     __stop___param - __start___param,
     &unknown_bootoption);
 pidhash_init();
 vfs_caches_init_early();
 sort_main_extable();
 trap_init();

 mm_init(); 

//当启动初始化完后,node_bootmem_map会被释放,系统初始化mem_map,

//利用struct page数据结构来管理所有的内存。

 ...

}

 

 

mem_init->free_all_bootmem_node->free_all_bootmem_core

 

//释放node_bootmem_map,使用mem_map管理物理内存,以页框为单位

static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
{
 int aligned;
 struct page *page;
 unsigned long start, end, pages, count = 0;

 if (!bdata->node_bootmem_map)
  return 0;

 start = bdata->node_min_pfn;
 end = bdata->node_low_pfn;

 /*
  * If the start is aligned to the machines wordsize, we might
  * be able to free pages in bulks of that order.
  */
 aligned = !(start & (BITS_PER_LONG - 1));

 bdebug("nid=%td start=%lx end=%lx aligned=%d/n",
  bdata - bootmem_node_data, start, end, aligned);

 while (start < end) {
  unsigned long *map, idx, vec;

  map = bdata->node_bootmem_map;
  idx = start - bdata->node_min_pfn;
  vec = ~map[idx / BITS_PER_LONG]; 

  //查询改为是否为"0",当空闲时将page标志为PG_Reserved

  if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) {
   int order = ilog2(BITS_PER_LONG);

   __free_pages_bootmem(pfn_to_page(start), order);
   count += BITS_PER_LONG;
  } else {
   unsigned long off = 0;

   while (vec && off < BITS_PER_LONG) {
    if (vec & 1) {
     page = pfn_to_page(start + off);
     __free_pages_bootmem(page, 0);
     count++;
    }
    vec >>= 1;
    off++;
   }
  }
  start += BITS_PER_LONG;
 }

 page = virt_to_page(bdata->node_bootmem_map);

 //得到node_bootmem_map的page地址
 pages = bdata->node_low_pfn - bdata->node_min_pfn;

 //得到物理内存的页框数
 pages = bootmem_bootmap_pages(pages);

 //node_bootmem_map共占了( (pages/8)>>12 )页
 count += pages;
 while (pages--)
  __free_pages_bootmem(page++, 0); //释放node_bootmem_map占用的页框

 bdebug("nid=%td released=%lx/n", bdata - bootmem_node_data, count);

 return count;
}

 

 

Author:Woodpecker <Pecker.hu@gmail.com>

### 关于 `dm-zoned` 的介绍 #### 设备映射器模块中的 `dm-zoned` 设备映射器(Device Mapper)是一个 Linux 内核框架,用于管理块设备的抽象层。它允许创建虚拟块设备,这些设备可以基于其他物理或逻辑块设备构建复杂的功能[^3]。 `dm-zoned` 是 Device Mapper 中的一个特定目标类型,旨在处理分区设备上的写入操作优化。对于现代大容量 SSD 和 HDD 存储介质而言,它们通常具有内部区域划分特性,即所谓的 Zoned Block Devices (ZBD),这使得某些部分只支持顺序写入而不能随机覆盖旧数据。为了更好地适应这种新型存储技术并提高性能,Linux 社区开发了 `dm-zoned` 来作为解决方案之一[^1]。 当使用 `dm-zoned` 时,会通过识别底层设备是否为分区分块设备来决定如何管理和调度 I/O 请求。如果检测到的是一个 zone-aware 或者 zoned 型态的目标,则该驱动程序将会按照相应的规则执行读/写命令序列化控制以及重定位等动作以确保最佳效率。 此外,在初始化过程中,`dm-init()` 函数负责启动整个 Device Mapper 模块,并调用一系列必要的子功能完成设置工作;而对于具体像 `dm-zoned` 这样的组件来说,其配置参数可能涉及到指定哪些实际磁盘应当被当作带状结构看待等问题。 ```c // Example of initializing a dm-zoned target within the kernel code. static int __init dm_zoned_init(void) { // Initialization logic here... } module_init(dm_zoned_init); ``` #### 数据结构关联 在实现上,`dm-zoned` 需要依赖一些核心的数据结构来进行有效的资源管理和请求转发。例如: - **struct dm_dev**: 描述了一个低级别的块设备实例,包含了指向底层 block_device 结构体的指针以及其他元信息,如文件访问权限和名称等属性。 - **set_capacity()**: 此函数用来设定给定通用磁盘对象 (`gendisk`) 所表示的实际大小,这对于正确反映新加入系统的分区或者调整现有卷尺寸非常重要[^2]。 综上所述,`dm-zoned` 提供了一种机制让操作系统能够充分利用带有内置区域特性的现代化固态硬盘和其他类型的持久性内存装置所带来的优势。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值