Day16 熟悉又陌生的 malloc()

前言

昨天看过了如何对VMA 进行操作,今天要来研究两个熟悉又陌生的函数, malloc()mmap()

malloc()

malloc() 是C语言中的虚拟记忆体分配函数,以下举两个例子进行比较,让大家更贴近 malloc()

流程图如下

以上是 malloc() 大致的呼叫顺序, malloc() 函数用在为 user space 空间分配行程定址空间,也就是分配一块VMA。 用简单的比喻来说 malloc() 就是先分给使用者一个空箱子,直到要真正使用箱子的时候才在里面装东西。
以下举出两个例子

void testA(void){
    char* bufA = malloc();
    ...
    *bufA = 100;
    ...
}

void testB(void){
    char* bufB = malloc(100);
    mlock(bufB, 100);
    ...
}

分别用两个行程A,B执行 testA()testB() ,两个例子同样使用了 malloc() 但是 testA() 先给一个虚拟位址,直到第四行实际要放入资料的时候,才会真正在实体记忆体找出一个位子。 testB() 则是利用 mlock 函数直接找到映射的实体记忆体了。以下来自man7

mlock(), mlock2(), and mlockall() lock part or all of the calling process's virtual address space into RAM, preventing that memory from being paged to the swap area.

testA() 在真正需要实体记忆体时,CPU会查询分页表,发现该虚拟位址映射的分页表为空,进而引发缺页异常(page fault),在缺页异常的处理中一页一页的分配实体记忆体。

若使用 printf() 对这两个行程输出 malloc() 分配的虚拟位址,会发现两个行程印出的结果相同,那麽这两个相同的虚拟位址是否会引发冲突呢?
答案是否定的,每个行程都有属於自己的分页表, 这个分页表放在 mm_struct 资料结构中的 pgd 里,pgd 会指向每个行程专属的分页表的起始位置。 在每个行程初始化的时候会建立专属的 mm_struct ,其中会包含属於该行程的分页表、管理VMA的红黑树、链表,所以每个行程管理自己的VMA都有自己的资料结构,因此不会因为虚拟位址相同而有所冲突。

以下是几个常见的记忆体分配的函数

void* malloc(size_t num); 

void* calloc(size_t num, size_t size);

malloc() 就如同上面讲的,先 num 大小的虚拟记忆体,但是不分配实际的记忆体,直到要使用的时候才实际分配实体记忆体。 calloc() 使用了两个参数, num 是总共要分配的记忆体大小, size 则是每个区块的大小是多少,并且立即分配实体记忆体并且将所有区块初始值设为0。 以下是简单使用两个函数的例子

// C program to demonstrate the use of calloc()
// and malloc()
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int* arr;

	// malloc() 分配大小是五个 int大小的虚拟记忆体
	// containing garbage values
	arr = (int*)malloc(5 * sizeof(int)); // 5*4bytes = 20 bytes
	// 砍掉上面分配的空间
	free(arr);

	// calloc() 分配五个int大小的空间并且初始化为0
	arr = (int*)calloc(5, sizeof(int));
	//砍掉上述的空间
	free(arr);
	return (0);
}

刚好想到另外两个长得很像的函数, vmalloc()kmalloc

void *vmalloc(unsigned long size)

void *kmalloc(size_t size, int flags);

vmalloc()size 代表要分配的大小, kmalloc()size 要分配的大小, flags 代表这段记忆体的标记是什麽。
这两个函数的只有微小的差异, kmalloc() 会分配连续的虚拟记忆体,同时也会分配连续的实体记忆体。kmalloc()vmalloc() 的差别在於後者分配的实体记忆体空间不是连续的。在普通的使用状态下,这两者并没有明显的差别, 在 Kernel 内kmallocvmalloc 常用的理由是因为效能问题, 当实体记忆体需要被 DMA 装置存取的时候,效能差异就会出现了, 因为使用 vmalloc() 需要进行映射,会让效能比较低, 不过 vmalloc() 可以分配比较大的空间。

kmalloc and vmalloc


<<:  第 15 天 有甚麽事先练再说( leetcode 019 )

>>:  [Day16] Arbitrary File Upload

Day.18 「从函式物件认识 作用域 与 提升!」 —— JavaScript 函式(Function) & 作用域(Scope) & 提升(Hoisting)

函数也是个物件型别,可以封装一些功能(程序码),在需要使用的时候执行功能(程序码)。 例如我们需要...

[Python 爬虫这样学,一定是大拇指拉!] DAY19 - Python:Requests 基本应用 (2)

今天要来讲的是,读取送出 Request 後拿回来的 Response。 读取 Response 以...

Day 11 - 在 VyOS 设定 BGP Peer

继上篇,我们安装好 FRRouting 後,我们先在 VyOS 上设定一下 BGP 吧! 环境 我们...

确保资讯安全的有效性,并达到符合性(合规性)要求,应优先遵循组织政策

-政策框架 组织应当遵守法律法规。管理团队应尽职尽责制定或审查政策以满足法律和监管要求。 组织政策...

予焦啦!产出可执行档

本节是以 Golang 上游 1a708bcf1d17171056a42ec1597ca8848c...