资讯

展开

Linux内存知识整理-01

作者:快盘下载 人气:

1. 概述

内存管理是内核最复杂同时也最重要的一部分。其特点在于非常需要处理器和内核之间的协
作。

内存管理的实现涵盖了许多领域;

1.1 Linux地址空间 

就我们所知;Linux内核一般将处理器的虚拟地址空间划分为两个部分。底部比较大的部分用于用户进程;顶部则专用于内核。虽然;在两个用户进程之间的;上下文切换期间会改变下半部分;但虚拟地址空间的内核部分总是保持不变。地址空间在用户进程和内核之间划分的典型比例为3∶1。如;给出4 GB虚拟地址空间;3 GB将用于用户空间而1 GB将用于内核。

Linux内存知识整理-01

 用户空间5中不同的内存段;

1.2 ARM Linux内存页 

 一个page大小为什么是4KB?

代码跟进;kernel/msm-5.4/arch/arm/include/asm/page.h

PAGE_SHIFT=12

如上图所示;可以计算: 2^ 12 = 4096  即4KB

有些同学可能会疑惑;为啥是KB不是kb?

^_^; 因为一个内存地址所代表的永远是1个字节即Byte 并非Bit

2.内存申请

TODO

2.1 用户空间

malloc是C标准提供的内存分配函数。

2.2 内核

2.2.1 kmalloc

TODO

2.2.2 kzalloc

/**
 * kzalloc - allocate memory. The memory is set to zero.
 * ;size: how many bytes of memory are required.
 * ;flags: the type of memory to allocate (see kmalloc).
 */
static inline void *kzalloc(size_t size, gfp_t flags)
{
	return kmalloc(size, flags | __GFP_ZERO);
}

如上code可以看出;kzalloc() 函数与 kmalloc() 非常相似;参数及返回值是一样的;可以说是前者是后者的一个变种;因为 kzalloc() 实际上只是额外附加了 __GFP_ZERO 标志。所以它除了申请内核内存外;还会对申请到的内存内容清零。

2.2.3 vmalloc

vmalloc 是三个接口中唯一一个无法保证申请连续内存的接口;如果申请的内存size大于一个page size 即4KB;则无法确保申请到连续内存。

2.2.4 标志位

  • GFP_ATOMIC —— 分配内存的过程是一个原子过程;分配内存的过程不会被;高优先级进程或中断;打断;无法休眠;
  • GFP_KERNEL —— 正常分配内存;可以休眠;不能再中断上下文中使用;但是可以在进程上下文中使用。
  • GFP_DMA —— 给 DMA 控制器分配内存;需要使用该标志;DMA要求分配虚拟地址和物理地址连续;。

2.2.5 使用上述三个接口分配的内存上限是多大呢?

如下代码分析;

kernel/msm-5.4/include/linux/slab.h

        -> static __always_inline void *kmalloc(size_t size, gfp_t flags)

                ->void *__kmalloc(size_t size, gfp_t flags)

void *__kmalloc(size_t size, gfp_t flags)
{
	struct kmem_cache *s;
	void *ret;

	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
		return kmalloc_large(size, flags);

	s = kmalloc_slab(size, flags);

	if (unlikely(ZERO_OR_NULL_PTR(s)))
		return s;

	ret = slab_alloc(s, flags, _RET_IP_);

	trace_kmalloc(_RET_IP_, ret, size, s->size, flags);

	ret = kasan_kmalloc(s, ret, size, flags);

	return ret;
}
EXPORT_SYMBOL(__kmalloc);
static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
{
	unsigned int order = get_order(size);
	return kmalloc_order_trace(size, flags, order);
}

 最大size 为;KMALLOC_MAX_CACHE_SIZE

 申请的内存size 大于 KMALLOC_MAX_CACHE_SIZE则输出trace。

 KMALLOC_MAX_CACHE_SIZE 定义在;kernel/msm-5.4/include/linux/slab.h

/*
 * Kmalloc array related definitions
 */

#ifdef CONFIG_SLAB
/*
 * The largest kmalloc size supported by the SLAB allocators is
 * 32 megabyte (2^25) or the maximum allocatable page order if that is
 * less than 32 MB.
 *
 * WARNING: Its not easy to increase this value since the allocators have
 * to do various tricks to work around compiler limitations in order to
 * ensure proper constant folding.
 */
#define KMALLOC_SHIFT_HIGH	((MAX_ORDER ; PAGE_SHIFT - 1) <= 25 ? 
				(MAX_ORDER ; PAGE_SHIFT - 1) : 25)
#define KMALLOC_SHIFT_MAX	KMALLOC_SHIFT_HIGH
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW	5
#endif
#endif

#ifdef CONFIG_SLUB
/*
 * SLUB directly allocates requests fitting in to an order-1 page
 * (PAGE_SIZE*2).  Larger requests are passed to the page allocator.
 */
#define KMALLOC_SHIFT_HIGH	(PAGE_SHIFT ; 1)
#define KMALLOC_SHIFT_MAX	(MAX_ORDER ; PAGE_SHIFT - 1)
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW	3
#endif
#endif

#ifdef CONFIG_SLOB
/*
 * SLOB passes all requests larger than one page to the page allocator.
 * No kmalloc array is necessary since objects of different sizes can
 * be allocated from the same page.
 */
#define KMALLOC_SHIFT_HIGH	PAGE_SHIFT
#define KMALLOC_SHIFT_MAX	(MAX_ORDER ; PAGE_SHIFT - 1)
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW	3
#endif
#endif

/* Maximum allocatable size */
#define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_MAX)
/* Maximum size for which we actually use a slab cache */
#define KMALLOC_MAX_CACHE_SIZE	(1UL << KMALLOC_SHIFT_HIGH)
/* Maximum order allocatable via the slab allocagtor */
#define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_MAX - PAGE_SHIFT)

可以查看内核.config配置来确认KMALLOC_SHIFT_HIGH;KMALLOC_SHIFT_MAX以及  KMALLOC_SHIFT_LOW。

 如下所示;CONFIG_SLUB=y


CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_VM_EVENT_COUNT_CLEAN_PAGE_RECLAIM is not set
CONFIG_SLUB_DEBUG=y
# CONFIG_SLUB_MEMCG_SYSFS_ON is not set
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_SLAB_MERGE_DEFAULT is not set
CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_SHUFFLE_PAGE_ALLOCATOR=y
CONFIG_SLUB_CPU_PARTIAL=y
CONFIG_SYSTEM_DATA_VERIFICATION=y
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
# end of General setup

 CONFIG_FORCE_MAX_ZONEORDER=11

CONFIG_QTI_QUIN_GVM=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_UNMAP_KERNEL_AT_EL0=y
CONFIG_HARDEN_BRANCH_PREDICTOR=y

 那么 KMALLOC_SHIFT_MAX =  (MAX_ORDER ; PAGE_SHIFT - 1) 即 11;12-1 = 22;

 #define KMALLOC_MAX_SIZE    (1UL << KMALLOC_SHIFT_MAX)

 可以算出;KMALLOC_MAX_SIZE    为 2^22 = 4,194,304

 4,194,304/1024 = 4096KB

 4096KB/1024 = 4MB

 所以;采用kzalloc 、kmalloc分配内存;最大为4MB。

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!