1、为什么会有这个函数?

我想主要的原因就是kmap_atomic在效率上要比kmap提升不少。

在kmap函数中,会有如下几个比较耗时的部分:

1)、page_address函数
2)、Sleep for somebody else to unmap their entries
代码如下:
171 ____________DECLARE_WAITQUEUE(wait, current); 
173 ______________set_current_state(TASK_UNINTERRUPTIBLE);
174____________add_wait_queue(&pkmap_map_wait,&wait);                                                                           
175 ____________unlock_kmap();
176 ____________schedule();
177 ____________remove_wait_queue(&pkmap_map_wait, &wait);
3)、lock_kmap函数,需要加锁啊!!!
相反kmap_atomic函数,从名字就能看出,原子操作一气呵成。。没有sleep,没有锁。

2、怎么实现的?需要考虑什么问题?

首先得知道这个函数的主要目的是实现page 到 vaddr的转化。
其次我们得考虑多cpu和多任务,大家知道     kernel可以在多个cpu上同时运行不同的task,然而它们共同使用一个内存地址空间,因此如何能保证N个cpu调用kmap_atomic不会将page映射到一个虚拟地址(vaddr)呢?

我们来看看kmap_atomic是如何实现的?

1)、定义一个percpu变量__kmap_atomic_idx,同时在当前cpu上禁用抢占,直到unmap的时候才开启,这样就保证了同一cpu其它任务不会调用该函数。除非该进程在unmap之前睡眠,如果真的那样,别的进程就很可能在同一cpu重入kmap_atomic函数了,然后就可能映射到同一虚拟地址,因此在原子映射期间最好不要休眠。
2)、设计了一个完美的公式

type = kmap_atomic_idx_push();  //递增一个percpu变量,返回递增后的结果,增加一个计算type的函数表示kmap_atomic函数可以重入,就是上面说的该进程在unmap之前睡眠情况,但一般情况下不会发生冲入,所以该值应该是1,unmap时该值会--。当然重入的次数是有限制的,不会超过KM_TYPE_NR。
    idx = type + KM_TYPE_NR*smp_processor_id();//不同的cpusmp_processor_id()的值是不同的,因此,不同的cpu得到的idx不同。
    vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);//不同的idx得到的vaddr就不同了。
    set_pte(kmap_pte-idx, mk_pte(page, prot)); //设置页表
    return (void *)vaddr;

总结,通过percpu变量+禁抢占+加计算公式,就实现了,不同cpu的不同进程调用kmap_atomic函数得到的vaddr是不同的。同时这也给我们实现atomic提供了一种思路,实际上atomic一般都会有一个percpu变量。

3、得到vaddr之后,页表的建立。
我们就以arm为例,来说明一下,arm初始化的时候,会通过create_mapping来创建一些页表,比如map_lowmem就会调用 create_mapping函数来建立整个低端内存的映射。

同样地在函数devicemaps_init中会有如下代码:
 967 ____map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
 968 ____map.virtual = 0xffff0000;
 969 ____map.length = PAGE_SIZE;
 970 ____map.type = MT_HIGH_VECTORS;
 971 ____create_mapping(&map);
这里有一点需要说明一点,虽然只映射了一个PAGE_SIZE,但是如果内核采用的二级页表(即存在pgd,pte),而不是一级页表(只有pgd)的话,会在create_mapping函数中,分配512个pte项(即512个pte指针ptep),远远大于KM_TYPE_NR个数。但是如果采用一级页表的话,这就会有问题,这种情况应该不能用kmap_atomic函数,因为通过TOP_PTE(vaddr)宏是得不到ptep的,因此目前代码中有如下保护:
 67 #ifdef CONFIG_DEBUG_HIGHMEM
 68 ____/*
 69 ____ * With debugging enabled, kunmap_atomic forces that entry to 0.
 70 ____ * Make sure it was indeed properly unmapped.
 71 ____ */
 72____BUG_ON(!pte_none((TOP_PTE(vaddr))));                                                                                     
 73 #endif

由此,我们可以看到kmap_atomic使用的是地址空间顶部的一小段地址空间(0xffff0000开始),内核逻辑将这一小段地址空间分成了若干个节(slot),每一节的大小是一个page的大小,可以用来映射一个page。虽然总共可用512个slot,但是只能用KM_TYPE_NR个,有点遗憾!!!

原文地址: http://blog.chinaunix.net/uid-26817832-id-3358944.html

内核 kmap_atomic分析相关推荐

  1. 《LINUX3.0内核源代码分析》第一章:内存寻址

    https://blog.csdn.net/ekenlinbing/article/details/7613334 摘要:本章主要介绍了LINUX3.0内存寻址方面的内容,重点对follow_page ...

  2. 从源码和内核角度分析redis和nginx以及java NIO可以支持多大的并发

    有人询问我网上一篇关于"redis为什么单线程这么快"的文章,我建议他不要看了,因为redis是单进程不是单线程,后面的意见不用看了,文章质量肯定不会很好,他也说了自己看了很久源码 ...

  3. linux内核自解压,Linux的初始内核自解压分析

    Linux的初始内核自解压分析 (2009-03-27 19:46:46) 标签: it Linux的初始内核解压 2007-09-19 15:02 来源:论坛整理 作者:lucian_yao [网友 ...

  4. 重载内核全程分析笔记

    标 题: [原创]重载内核全程分析笔记 作 者: Speeday 时 间: 2013-08-20,20:19:46 链 接: http://bbs.pediy.com/showthread.php?t ...

  5. Linux2.6 内核进程调度分析

    Linux2.6 内核进程调度分析    进程的调度时机与引起进程调度的原因和进程调度的方式有关.在 2.6 中,除核心应用     主动调用调度器之外, 核心还在应用不完全感知的情况下在以下三种时机 ...

  6. windows 内核情景分析

    原文很长:先转部分过来,有时间看一下: 一 windows 内核情景分析---说明 说明 本文结合<Windows内核情景分析>(毛德操著).<软件调试>(张银奎著).< ...

  7. Windows内核系统调用分析

    系统调用 进程 --> 调用OS API:OS进程管理 --> 调配进程. 仅从用户进程角度,OS就像是一个被动响应的运行时库.Windows提供了一个系统调用界面作为外层,即Win32A ...

  8. Gloomy对Windows内核的分析

    /Files/ddlzq/Gloomy对Windows内核的分析.pdf 转载于:https://www.cnblogs.com/ddlzq/archive/2010/09/03/1817244.ht ...

  9. 《LINUX3.0内核源代码分析》第二章:中断和异常 【转】

    转自:http://blog.chinaunix.net/uid-25845340-id-2982887.html 摘要:第二章主要讲述linux如何处理ARM cortex A9多核处理器的中断.异 ...

最新文章

  1. linux挂载分区失败,Ubuntu分区挂载错误与Grub引导错误的修复
  2. asp.net控件开发基础(21)
  3. mysql left join on_mysql,left join on
  4. 【转】MyBatis缓存机制
  5. 时间戳转中国人能看得懂的日期格式 yy-mm-dd
  6. 域domain user用户对本地NTFS磁盘的写入权限问题
  7. AD如何清理过期电脑
  8. 小规模纳税人季度申报流程指导
  9. 内存——CPU、内存以及磁盘是如何交互的
  10. 陕西年内建成1万个5G基站,实现全省所有地级市覆盖5G网络
  11. oracle表分区设计_论oracle分区表的创建与维护
  12. 服务器定时关机 修改时间,服务器每周 设置定时关机
  13. 产品读书《极简生活法则》
  14. android listview 美化,Android界面美化 -- 自定义ListView分割线
  15. 我的物联网大学【第六章】:个人英雄主义和组织效率的矛盾
  16. 以太坊:Web3.js 0.20 使用说明
  17. 如何用matlab画紫罗兰,[转载]基于MATLAB的快速傅立叶分析程序设计
  18. 大学计算机基础实用教程重点知识,大学计算机基础实用操作教程
  19. 数据结构之快速排序算法(C语言版)
  20. 原子核的加法wy.xuexi.biz

热门文章

  1. [iphone]XML 解析 之 TBXML 介绍
  2. DLL动态链接库的工作原理
  3. 常见缓存算法和LRU与LFU的c++实现
  4. [云炬创业基础笔记]第七张创业团队测试9
  5. 科大星云诗社动态20210319
  6. 干货 | 机器学习正在面临哪些主要挑战?
  7. Ubuntu通过windows代理上网
  8. c++中的 单例模式(singleton)和双检测锁(Double-Checked Locking)
  9. 面向对象的C语言编程-DynamicLinkageGenericFunctions--C语言中的偷梁换柱
  10. 基于STM32,无人船岸基信息处理代码--python实现