当前位置: 首页 > news >正文

linux内核-写时复制之实验+源码分析

实验

相信大家都听过大名鼎鼎的copy on write技术,并且学习过原理。但是可能对于代码中具体的发生场景,脑海中可能没有实体的映射。下面使用1个例子说明copy on write的发生时间。

有这么一个程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>// 打印当前进程的内存占用(常驻集大小)
void print_memory_usage(const char* stage) {FILE* file = fopen("/proc/self/status", "r");if (!file) {perror("fopen");return;}char line[256];while (fgets(line, sizeof(line), file)) {if (strncmp(line, "VmRSS:", 6) == 0) {printf("[%s] Memory Usage (VmRSS): %s", stage, line + 6);break;}}fclose(file);
}int main() {size_t size = 100 * 1024 * 1024; // 分配 100 MBvoid* ptr = malloc(size);if (!ptr) {perror("malloc");return 1;}printf("Step 1: After malloc (before memset)\n");print_memory_usage("After malloc");sleep(3);  // 给用户一点时间观察memset(ptr, 0, size); // 写入触发物理内存分配printf("Step 2: After memset (after touching memory)\n");print_memory_usage("After memset");sleep(3);  // 给用户一点时间观察free(ptr);printf("Step 3: After free\n");print_memory_usage("After free");return 0;
}

编译+运行

编译:

gcc do_copy_on_write.c -o do_copy_on_write

运行:

./do_copy_on_write

各部分说明

1. 分配内存(malloc)

void* ptr = malloc(size);

分配了一块大小为 100MB 的虚拟内存。此时操作系统只分配了虚拟地址空间,并没有实际分配物理内存页(因为还没有使用它)。程序紧接着打印此时的内存使用情况(VmRSS):

print_memory_usage("After malloc");

2.让程序睡眠3秒

  • 程序会 sleep(3) 秒,可以有时间手动观察或记录当前内存(可以用 tophtop 或查看程序输出)。

  • 你会发现此时内存几乎没有明显增长,只有很小的常驻内存(程序自身的开销)。

3. 访问内存触发分配(memset)

memset(ptr, 0, size);
  • 使用 memset 将这 100MB 全部设置为 0,相当于每个内存页都被写入了一次

  • 这会触发操作系统的延迟物理页分配机制,因为每个页第一次被写入,就必须真正分配物理内存。

  • 然后再次调用 print_memory_usage 打印新的 VmRSS,这时你会看到内存暴涨到 100MB 左右

 4. 最后释放内存

整个程序完整的输出为:

./a.out
Step 1: After malloc (before memset)
[After malloc] Memory Usage (VmRSS):         952 kB
Step 2: After memset (after touching memory)
[After memset] Memory Usage (VmRSS):      103912 kB
Step 3: After free
[After free] Memory Usage (VmRSS):          1536 kB

源码分析

TODO

相关文章:

  • Ajax 核心知识点全面总结
  • day40- 硬件学习之 51单片机II (中断处理)
  • 【MySQL】MySQL 数据库操作与设计
  • 网络编程TCP与UDP
  • 《开窍》读书笔记9
  • vulnhub-Matrix-Breakout 2 Morpheus
  • 网络NAT是什么
  • Go 语言中的条件判断和for 循环
  • 详解 MyBatis - Plus 服务层设计:让 CRUD 更高效、业务拓展更灵活——补充
  • ArrayList源码分析
  • Arrays.asList() 的不可变陷阱:问题、原理与解决方案
  • 全面理解 JVM 垃圾回收(GC)机制:原理、流程与实践
  • DHCP实战
  • Quick BI 自定义组件开发 -- 第三篇 echart 组件开发图表,使用动态数据
  • 知识图谱和知识库的区别:详细解读
  • react框架-路由的嵌套以及参数传递与编程化
  • 【Golang面试题】开多个线程和开多个协程会有什么区别?
  • 质量小议55 - 搜索引擎与AI
  • 使用批处理自动拉取截屏图片
  • 大模型知识库RAG框架,比如LangChain、ChatChat、FastGPT等等,哪个效果比较好
  • javascript用什么软件编写/南昌seo排名扣费
  • 网站做的app有哪些/人工智能培训班收费标准
  • 成品源码1688网站免费/凡科建站快车
  • 爱站权重查询/友链申请
  • 北京网站制作/安卓系统优化软件
  • 如何建设微信网站/当日网站收录查询统计