缓存为什么会有冷热?

究其原因,是因为对于内存的访问,可能是CPU发起的,也可以是DMA设备发起的。

如果是CPU发起的,在CPU的硬件缓存中,就会保存相应的页内容。如果这个页本来没有存在于硬件缓存中,那么它的到来,势必会将原本为其他的页缓存的内容挤出硬件缓存。

但是,如果对于内存的访问是由DMA设备发起的,那么该页不会被CPU访问,就不需要在CPU的硬件缓存中进行缓存,也不会对已经缓存在硬件缓存中的页内容造成伤害。

在Linux操作系统中,每个内存区域(Zone)都分配了hot cache和cold cache,hot cache用来缓存那些很可能被CPU的硬件缓存收纳了的页。

hot/cold cache只处理单页分配的情况。

   1: /*
2: * Really, prep_compound_page() should be called from __rmqueue_bulk(). But
3: * we cheat by calling it from here, in the order > 0 path. Saves a branch
4: * or two.
5: */
6: static inline
7: struct page *buffered_rmqueue(struct zone *preferred_zone,
8: struct zone *zone, int order, gfp_t gfp_flags,
9: int migratetype)
10: {
11: unsigned long flags;
12: struct page *page;
13: int cold = !!(gfp_flags & __GFP_COLD);
14:
15: again:
16: if (likely(order == 0)) {
17: struct per_cpu_pages *pcp;
18: struct list_head *list;
19:
20: local_irq_save(flags);
21: pcp = &this_cpu_ptr(zone->pageset)->pcp;
22: list = &pcp->lists[migratetype];
23: if (list_empty(list)) {
24: pcp->count += rmqueue_bulk(zone, 0,
25: pcp->batch, list,
26: migratetype, cold);
27: if (unlikely(list_empty(list)))
28: goto failed;
29: }
30:
31: if (cold)
32: page = list_entry(list->prev, struct page, lru);
33: else
34: page = list_entry(list->next, struct page, lru);
35:
36: list_del(&page->lru);
37: pcp->count--;
38: } else {
39: if (unlikely(gfp_flags & __GFP_NOFAIL)) {
40: /*
41: * __GFP_NOFAIL is not to be used in new code.
42: *
43: * All __GFP_NOFAIL callers should be fixed so that they
44: * properly detect and handle allocation failures.
45: *
46: * We most definitely don't want callers attempting to
47: * allocate greater than order-1 page units with
48: * __GFP_NOFAIL.
49: */
50: WARN_ON_ONCE(order > 1);
51: }
52: spin_lock_irqsave(&zone->lock, flags);
53: page = __rmqueue(zone, order, migratetype);
54: spin_unlock(&zone->lock);
55: if (!page)
56: goto failed;
57: __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order));
58: }
59:
60: __count_zone_vm_events(PGALLOC, zone, 1 << order);
61: zone_statistics(preferred_zone, zone, gfp_flags);
62: local_irq_restore(flags);
63:
64: VM_BUG_ON(bad_range(zone, page));
65: if (prep_new_page(page, order, gfp_flags))
66: goto again;
67: return page;
68:
69: failed:
70: local_irq_restore(flags);
71: return NULL;
72: }

buffered_rmqueue用于从冷热分配器中分配单页的缓存页。

如果gfp_flags中指定的__GFP_COLD,则从冷缓存中分配一页,否则,从热缓存中分配。

Linux内核的冷热缓存的更多相关文章

  1. linux内核的冷热页分配器

    先说说cpu的cache,和cpu的cache比起来访问主内存是非常慢的,为了加快速度根据本地性原则,cpu在访问主内存的时候会把附近的一块数据都加载到cpu的cache里,之后读写这块数据都是在ca ...

  2. 20169207《Linux内核原理与分析》第十周作业

    这周除了阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第15,16章外.我们还需要接着完成学习MOOC「Linux内核分析」第八讲「Linux系统 ...

  3. 2017-2018-1 20179202《Linux内核原理与分析》第九周作业

    进程的切换和系统的一般执行过程 1.知识总结 (1)进程调度的时机: 中断处理过程直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule(). 内核线程是一 ...

  4. 2017-2018-1 20179205《Linux内核原理与设计》第九周作业

    <Linux内核原理与设计>第九周作业 视频学习及代码分析 一.进程调度时机与进程的切换 不同类型的进程有不同的调度需求,第一种分类:I/O-bound 会频繁的进程I/O,通常会花费很多 ...

  5. Linux内核设计与实现 总结笔记(第十六章)页高速缓存和页回写

    页高速缓存是Linux内核实现磁盘缓存.磁盘告诉缓存重要源自:第一,访问磁盘的速度要远远低于访问内存. 第二,数据一旦被访问,就很有可能在短期内再次被访问到.这种短时期内集中访问同一片数据的原理称作临 ...

  6. 模仿Linux内核kfifo实现的循环缓存

    想实现个循环缓冲区(Circular Buffer),搜了些资料多数是基于循环队列的实现方式.使用一个变量存放缓冲区中的数据长度或者空出来一个空间来判断缓冲区是否满了.偶然间看到分析Linux内核的循 ...

  7. linux内核数据结构学习总结

    目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...

  8. 内存管理——linux内核学习

    买了<深入Linux内核架构>这本书准备了解一下linux内核机制.但是最开始看了十几页感觉看着很累,本来都准备弃了 过了段时间看见一个面经有linux内核的内容,于是就照着那个先把内存管 ...

  9. Linux内核内存管理架构

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射.页面分配.页面回收.页面交换.冷热页面.紧急页面.页面碎片管理.页面缓存.页面统计等,而且对性能也有很高的要 ...

随机推荐

  1. Java 生成 JNI 头文件

    [参考文章]:javah javac 命令行生成native的方法教程 [参考文章]:用javah 导出类的头文件, 常见的错误及正确的使用方法 项目需要调用 C++动态库,由于项目包结构发生变化,需 ...

  2. ThinkPHP Redis实现模拟队列

    1.入队操作: //入队 public function enqueue() { $redis = new \Redis(); $redis->connect('127.0.0.1',6379) ...

  3. CentOS 6.5系统上安装SVN服务器

    有效地管理源代码的方式是使用工具去帮助我们管理 , SVN(Subversion)就是目前主流的源代码管理工具 , 也称为版本控制工具. 本文主要介绍CentOS6.5上安装SVN服务器,配置SVN服 ...

  4. nginx切割日志脚本

    nginx切割日志脚本 #!/bin/bash #cut nginx log #2018年9月26日14:26:44 #by jiajiezhao ########################## ...

  5. 【java设计模式】(3)---代理模式(案例解析)

    设计模式之代理模式 一.概述 1.什么是代理模式? 解释第一遍:代理模式主要由三个元素共同构成: 1)一个接口,接口中的方法是要真正去实现的. 2)被代理类,实现上述接口,这是真正去执行接口中方法的类 ...

  6. Android:剖析源码,随心所欲控制Toast显示

    前言 Toast相信大家都不会陌生吧,如果对于Toast不甚了解,可以参考我的上一篇博客<Android:谈一谈安卓应用中的Toast情节>,里面有关于Toast基础比较详细的介绍.但是如 ...

  7. java~spring-ioc的使用

    spring-ioc的使用 IOC容器在很多框架里都在使用,而在spring里它被应用的最大广泛,在框架层面 上,很多功能都使用了ioc技术,下面我们看一下ioc的使用方法. 把服务注册到ioc容器 ...

  8. 为VIP解决问题时写的源码

    平时为学生们解决问题时,建立的项目源代码,方便大家学习与讨论. 开源DEMO列表 1. https://github.com/bfyxzls/student_orderBy 2. https://gi ...

  9. 基于spark实现并行化Apriori算法

    详细代码我已上传到github:click me 一. 实验要求         在 Spark2.3 平台上实现 Apriori 频繁项集挖掘的并行化算法.要求程序利用 Spark 进行并行计算. ...

  10. leetcode — palindrome-partitioning

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Source : https://o ...