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

win7网站后台无法编辑vr网站建设

win7网站后台无法编辑,vr网站建设,google推广妙招,网站专题页优化文章说明#xff1a; Linux内核版本#xff1a;5.0 架构#xff1a;ARM64 参考资料及图片来源#xff1a;《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 触发页面回收 Linux内核中触发页…文章说明 Linux内核版本5.0 架构ARM64 参考资料及图片来源《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址 zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 触发页面回收 Linux内核中触发页面回收的机制大致有3个 直接页面回收机制。在内核态里调用页面分配接口函数alloc_pages()分配物理页面时由于系统内存短缺不能满足分配请求因此内核会直接自陷到页面回收机制尝试回收内存来解决当前的燃眉之急这称为直接页面回收。周期性回收内存机制。这是kswapd内核线程的工作职责。当内核路径调用alloc_pages() 分配物理页面时由于系统内存短缺没法在低水位情况下分配出内存因此会唤醒kswapd内核线程来异步回收内存。slab收割机slab shrinker机制。这是用来回收slab对象的。当内存短缺时直接页 面回收和周期性回收内存两种机制都会调用slab收割机机制来回收slab对象。slab机制分配的内存主要用于slab对象和kmalloc接口也可用于内核空间的内存分配。 注意 直接回收内存的进程主体是调用者本身。直接回收内存是同步回收这会阻塞调用者进程的执行。kswapd本身是内核线程它和调用者的关系是异步的。如test进程尝试调用alloc_pages()来分配内存当发现在低水位情况下无法分配出内存时它唤醒kswapd内核线程。这时kswapd 内核线程就开始执行页面回收工作了。test进程会继续尝试其他办法来分配内存如调用直接回收内存机制。 页面回收机制的主要调用路径如下图所示 下面将根据源码围绕这张图中的关键部分进行讲解。 2. kswapd内核线程 kswapd是Linux内核中一个非常重要的内核线程它负责在内存不足的情况下回收页面。kswapd内核线程初始化时会为系统中每个NUMA内存节点创建一个名为“kswapdd”的内核线程。 触发周期性回收内存机制的逻辑如下所示 balance_pgdat()函数是回收页面的主函数其主体函数是一个很长的while循环简化后的代码框架如下 static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx) {...restart:// 使用 sc.priority 表示页面扫描粒度或者优先级sc.priority DEF_PRIORITY;do {...// 检查这个内存节点中是否有合格的 zone其水位高于高水位并且能分配出 2 的 sc.priority 次方个连续的物理页面balanced pgdat_balanced(pgdat, sc.order, classzone_idx);if (!balanced nr_boost_reclaim) {nr_boost_reclaim 0;goto restart;}// 若符合条件则跳转到 out 标签处if (!nr_boost_reclaim balanced)goto out;...// 对匿名页面的活跃 LRU 链表进行老化age_active_anon(pgdat, sc);...// 回收页面的核心函数if (kswapd_shrink_node(pgdat, sc))raise_priority false;...if (raise_priority || !nr_reclaimed)// 不断加大扫描粒度sc.priority--;} while (sc.priority 1);if (!sc.nr_reclaimed)pgdat-kswapd_failures;out:if (boosted) {...// 若设置了 boosted则唤醒 kcompactd 内核线程wakeup_kcompactd(pgdat, pageblock_order, classzone_idx);}...// 返回已经回收的页面数量return sc.order; }3. shrink_node()函数 shrink_node()函数用于扫描和回收内存节点中所有可回收的页面还会做一些数据的统计和反馈工作 // pgdat 表示内存节点 // sc 表示扫描的控制参数 static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) {...do {...// 遍历 memory cgroup调用 shrink_node_memcg() 回收页面do {...// 基于内存节点的页面回收函数它会被 kswapd 内核线程和直接页面回收机制调用shrink_node_memcg(pgdat, memcg, sc, lru_pages);node_lru_pages lru_pages;if (sc-may_shrinkslab) {// shrink_slab() 调用内存管理系统中的 shrinker 接口用于回收 slab 对象shrink_slab(sc-gfp_mask, pgdat-node_id,memcg, sc-priority);}// vmpressure() 函数通过计算 scanned/reclaimed 比例来判断内存压力vmpressure(sc-gfp_mask, memcg, false,sc-nr_scanned - scanned,sc-nr_reclaimed - reclaimed);...} while ((memcg mem_cgroup_iter(root, memcg, reclaim)));...// 判断当前进程是否是 kswapd 内核线程if (current_is_kswapd()) {// 若当前系统回写的页面数量等于这一轮页面扫描的数量说明这些系统有大量回写页// 面因此应该设置 PGDAT_WRITEBACK表示发现有大量页面正在等待回写到磁盘if (sc-nr.writeback sc-nr.writeback sc-nr.taken)set_bit(PGDAT_WRITEBACK, pgdat-flags);// 若当前系统的脏页数量等于正在块设备 I/O 上进行回写数据的页面数量说明系统有大量// 页面堵塞在块设备的 I/O 操作上因此应该设置 PGDAT_CONGESTED表示内存节点中发// 现有大量脏页拥堵在一个 BDI 设备中if (sc-nr.dirty sc-nr.dirty sc-nr.congested)set_bit(PGDAT_CONGESTED, pgdat-flags);// 若当前系统还没有开始回写的脏页数量等于这一轮扫描的文件映射的页面数量说明系统有// 大量脏页面因此应该设置 PGDAT_DIRTY表示发现有大量的脏文件页面if (sc-nr.unqueued_dirty sc-nr.file_taken)set_bit(PGDAT_DIRTY, pgdat-flags);// 统计数据有 immediate 个页面说明在处理正在回写的页面时发现已经有大量的页面在等待回写// 因此需要调用 congestion_wait() 函数让页面等待 100msif (sc-nr.immediate)congestion_wait(BLK_RW_ASYNC, HZ/10);}...// 当前页面回收者是直接页面回收者的情况下// current_may_throttle() 判断当前回写设备是否拥堵若拥堵则睡眠一段时间来缓解拥堵情况。// 若成功回收了 sc-nr_reclaimed 个页面返回 trueif (!sc-hibernation_mode !current_is_kswapd() current_may_throttle() pgdat_memcg_congested(pgdat, root))wait_iff_congested(BLK_RW_ASYNC, HZ/10);// 通过这一轮中回收页面的数量和扫描页面的数量来判断是否需要继续扫描} while (should_continue_reclaim(pgdat, sc-nr_reclaimed - nr_reclaimed,sc-nr_scanned - nr_scanned, sc));...return reclaimable; }4. shrink_active_list()函数 shrink_active_list()函数用于扫描活跃LRU链表包括匿名页面或者文件映射页面把最近一直没有人访问的页面添加到不活跃LRU链表中。 // nr_to_scan待扫描页面的数量 // lruvecLRU 链表集合 // sc页面扫描控制参数 // lru待扫描的 LRU 链表类型 static void shrink_active_list(unsigned long nr_to_scan,struct lruvec *lruvec,struct scan_control *sc,enum lru_list lru) {...// 定义 3 个临时链表LIST_HEAD(l_hold); /* The pages which were snipped off */LIST_HEAD(l_active);LIST_HEAD(l_inactive);...// is_file_lru() 判断链表是否为文件映射的 LRU 链表int file is_file_lru(lru);// 从 lruvec 中返回内存节点描述符 pgdatstruct pglist_data *pgdat lruvec_pgdat(lruvec);...// 在操作链表时有一个保护 LRU 的自旋锁 pgdat-lru_lockspin_lock_irq(pgdat-lru_lock);// isolate_lru_pages() 批量地把 LRU 链表的部分页面迁移到临时链表l_hold链表中// 这样可以缩短加锁的时间nr_taken isolate_lru_pages(nr_to_scan, lruvec, l_hold,nr_scanned, sc, isolate_mode, lru);// 增加内存节点中的 NR_ISOLATED_ANON 计数__mod_node_page_state(pgdat, NR_ISOLATED_ANON file, nr_taken);// 增加 recent_scanned[] 计数reclaim_stat-recent_scanned[file] nr_taken;...// 页面迁移到临时链表 l_hold 后释放 pgdat-lru_lock 自旋锁spin_unlock_irq(pgdat-lru_lock);// while 循环扫描临时链表 l_hold 中的页面有些页面会添加到 l_active 中// 有些会添加到 l_inactive 中while (!list_empty(l_hold)) {cond_resched();// lru_to_page() 从链表中取一个页面page lru_to_page(l_hold);list_del(page-lru);// 如果页面是不可回收的就把它放回不可回收的 LRU 链表中if (unlikely(!page_evictable(page))) {putback_lru_page(page);continue;}...// page_referenced() 函数返回该页面最近访问、引用 PTE 的个数// 若返回 0表示最近没有访问、引用if (page_referenced(page, 0, sc-target_mem_cgroup,vm_flags)) {...}// 如果页面没有被引用清除页面的 PG_Active 标志位并且将页面加入 l_inactive 链表中ClearPageActive(page); /* we are de-activating */SetPageWorkingset(page);list_add(page-lru, l_inactive);}// 这段加锁期间把 l_inactive 和 l_active 链表中的页面迁移到相应的 LRU 链表中spin_lock_irq(pgdat-lru_lock);// 把最近引用的页面数量保存到 recent_rotated 中以便下一次扫描时在// get_scan_count() 中重新计算匿名页面和文件映射页面 LRU 链表的扫描比值reclaim_stat-recent_rotated[file] nr_rotated;nr_activate move_active_pages_to_lru(lruvec, l_active, l_hold, lru);nr_deactivate move_active_pages_to_lru(lruvec, l_inactive, l_hold, lru - LRU_ACTIVE);__mod_node_page_state(pgdat, NR_ISOLATED_ANON file, -nr_taken);spin_unlock_irq(pgdat-lru_lock);mem_cgroup_uncharge_list(l_hold);// l_hold 链表中是剩下的页面可以释放free_unref_page_list(l_hold);trace_mm_vmscan_lru_shrink_active(pgdat-node_id, nr_taken, nr_activate,nr_deactivate, nr_rotated, sc-priority, file); }5. shrink_inactive_list()函数 shrink_inactive_list()函数扫描不活跃LRU链表以尝试回收页面并且返回已经回收的页面的数量。该函数的逻辑过于复杂因此这里用图来理解如下图所示感兴趣的道友可以根据该流程图去阅读该函数的源代码 6. 页面回收的流程图
http://www.zqtcl.cn/news/679721/

相关文章:

  • 做头发个人网站制作素材dw中做网站的步骤
  • 学校网站做几级等保网页制作与维护
  • 十堰外贸网站建设松滋做网站
  • 网站导航条青浦徐泾网站建设
  • 厦门网站建设一般多少钱店铺域名是什么意思
  • 网站关键词搜索排名怎么做雅奇小蘑菇做网站好不好用
  • 手机网站案例建设网站地图素材
  • 企业网站制作比较好的如何设计一个网页首页代码
  • 维护网站成本网站建设进度图
  • asp.net做织梦网站设计手机网站建设
  • 江苏省住房和城乡建设局网站首页北京大型网站制作公司
  • 网站改版工作方案网站设计技能培训
  • 佳木斯市网站建设淄博网站开发招聘
  • 学习软件的网站先备案先建网站
  • 建立网站 知乎常州网站制作机构
  • 洛阳建设网站上海高端室内设计事务所
  • 做高清图的网站wordpress分类自定义文字
  • 创建站点如何做网站如何利用分类信息网站做推广
  • wordpress 拍卖插件找文网优化的技术团队
  • 建站素材网自助餐火锅网站建设
  • 企业型网站建设方案农村电商网站设计与发展现状
  • 建站快车凡科企业网站建设合同(一)
  • 阜平网站建设在广州做seo找哪家公司
  • 怎么做农家乐联盟网站六安建设机械网站
  • 网站开发行业标准江苏网站开发公司
  • 服装技术支持东莞网站建设如何加强企业网站建设论文
  • 中英双语网站怎么做深圳勘察设计协会
  • 用dw做网站维护教程梧州网站建设制作
  • 网站代运营公司有哪些深圳小区封闭最新通知
  • 江西网站设计服务网站开发所需费用明细