0xC0000000个人笔记:

0xC0000000:3GB的起始地址。一个进程分为两个部分:私有和全局。私有部分是指进程自己的代码,而全局部分则是指内核代码。局部是进程私有的,而全局则是所有进程公用的。理解这个只需要理解页表即可:4GB内存,0-3GB用于用户,3-4GB用于内核,也就是说AB两个进程,页表中0-3GB分别映射到了不同的物理内存,而3-4GB都是映射到了同一片物理内存即内核代码段(内核可以通过复制把内核部分页表项复制到用户进程的页表中)。(“《ULK》  P74翻译版“原话”:主内核全局目录的最高目录项部分作为参考模型,给每个普通进程对应的页全局目录项提供参考模型 。 ”)。

csdn博客-内核的连接脚本vmlinux.lds中

. = PAGE_OFFSET + TEXT_OFFSET; 将我们的内核代码编译到0xc0000000+TEXT_OFFSET处。就像我们做的嵌入式实验一样,编译时我们的代码默认会加载到0x30000000处执行一样,而启动代码刚开始是加载到0x0处,编译好的代码需要在地址0x0处执行一段,因为在把我们的代码复制到0x30000000之前代码中使用的都是相对跳转和相对偏移,并不涉及存放数据的地址,所以即使我们编译时设定执行地址是0x30000000而实际在地址0x0处执行并不会出错。(要想深刻理解偏移量,则可以尝试写一个程序,从实模式跳入保护模式,见《x86汇编语言:从实模式到保护模式》第十一章,当你犯够了错误才能理解了这个偏移量使用不当致错的原因,一旦理解,那么许多东西就很容易懂了)。

linux也一样,我们编译linux是编译到PAGE_OFFSET + TEXT_OFFSET处,而系统启动时并不是一开始就跳到0xC00000000以后的内核空间,而是会跳到固定地址(8086是FFFF:0000)处执行,然后再跳到内核空间。(PAGE_OFFSET:linux-2.6.0\include\asm-i386\page.h,i386中是0xc0000000

TEXT_OFFSET:linux-2.6.0\arch\arm\Makefile,其中定义了TEXTADDR 0xc0008000,可得出TEXT_OFFSET=0x8000)。linux-2.6.0\arch\i386\kernel\head.S中使用了三个变量,pg0,swapper_pg_dir,mmu_cr4_features,linux以后肯定会开启分页,所以这些变量的地址都是虚拟地址,而因为此时还未开启分页,所以又必须使用物理地址,所以我们会注意到在使用这三个变量时使用的都是  (var_addr - __PAGE_OFFSET)来获得变量地址,也就是说将虚拟地址直接减去一个固定的值就得到了其真正的物理地址,如《ULK》第三版P74倒数两行所说(他只是举了个例子说是8M):“分页第一个阶段的目标是允许在实模式和保护模式下(笔者注:此时肯定开启了分页)都很容易对这8MB寻址。因此内核必须创建一个映射,把从0x0~0x007fffff的线性地址和从0xc0000000~0xc07fffff的线性地址映射到从0x0~0x007fffff的物理地址”,所以说linux内核页表0xc0000000开始的一段线性地址空间必须映射到0x0处。因为32位的话linux内核只占据3GB到4GB这1GB的线性地址空间,所以需要留出一部分线性地址空间用做高端内存,即用做动态映射

内核逻辑地址&&内核虚拟地址个人笔记:

理解了0xc0000000,那么内核逻辑地址和内核虚拟地址就很好理解了。因为0xc0000000开始的一部分连续线性地址必须映射到物理地址0x0处开始的一段连续内存,那么这部分物理地址空间就可以看做一个段地址为0x0的段。举个例子,假设有线性地址0xc09110111,采用的是直接映射,于是便可以得到其对应的物理地址为0x00911011(0x00911011=0xc09110111-0xc00000)因为段基址为0,那么这个0x009110111便可以看做是段内偏移,而X86系列的段式内存管理中把这个段内偏移叫做逻辑地址,其实际地址=段地址(0)+段内偏移=段内偏移,也就是说可以把这个采用直接映射的与物理地址一 一对应的线性地址部分看做是以0x0为段基址的段的一个段内偏移(线性地址减去一个固定值便可得到,这个固定值就是0xC0000000),所以给这段线性地址重新取个名字,叫逻辑地址,所以说linux的内核逻辑地址一定是内核虚拟地址,而因为linux中有一部分线性地址(比如高端内存)不是采用直接映射的方式,.假设有个地址0xCfff0000不属于直接映射的线性地址范围,其映射的物理地址是随机的不等于段地址(0xC)+(0xCfff0000),也就是不可以把线性地址0xCfff0000看做段内偏移,所以说内核虚拟地址不一定是内核逻辑地址。

高端内存个人笔记:

假设PC安装了2G内存

因为linux中一个进程分为3GB用户空间和1GB内核空间,即线性地址0xc0000000~0xffffffff,故内核最多只能访问0xffffffff-0xc0000000即1GB内存。linux将0xC0000000开始的896MB虚拟地址直接映射到物理地址0~0x896MB处,然后当假设内核需要访问大于1Gb的物理地址时便将剩下的128M左右的虚拟地址空间映射都你想要访问的物理地址。举个例子,内核想要访问0x40000000(1GB)~0x40000000+X之间X M大小的物理地址空间时,便将0xf7000000~0xffffffff之间的一部分(假设从0xf9000000开始)线性地址即X M线性地址动态的映射到物理地址0x40000000~0x40000000+X,于是内核访问线性地址0xf9000000+Y便可以访问到物理地址0x40000000+Y(Y<X),也就是说临时映射,访问完了大于1Gb的物理地址后就释放这个临时的映射以便可以重复利用,也就是说当其他进程占据高端内存却没有释放时便会导致高端内存越来越少,以致当其他进程的内核部分想使用大于1GB的物理地址时无法办到

回弹缓冲区-百度百科:

DMA:设备使用的是物理地址,所以需要连续的物理页,所以高端内存除非映射到连续物理页,否则一般使用直接映射部分的地址空间做缓冲区

linux 神秘的0xC0000000内核逻辑地址内核虚拟地址直接映射高端内存相关推荐

  1. linux 物理内存用完了_Linux用户空间与内核空间(理解高端内存)

    Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图. Linux内核地址空间划分 通常32位L ...

  2. Linux用户空间与内核空间(理解高端内存)

    目录 Linux内核地址映射模型 Linux内核地址空间划分 Linux内核高端内存的由来 Linux内核高端内存的理解 Linux内核高端内存的划分 常见问题 小结 1.虚拟内核空间到物理空间的映射 ...

  3. linux 各用户内存_Linux用户空间与内核空间(理解高端内存)

    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数 ...

  4. Linux内核高端内存

    Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图.   Linux内核地址空间划分 通常32 ...

  5. linux内核1G虚拟地址空间的映射规则以及什么是高端内存?

    前面我们讲了,在32位linux内核里,内核地址空间是0xc0000000~0xffffffff, 大小1G:内核地址空间是0x00000000~0xbfffffff,大小3G.当内核代码访问内存时, ...

  6. Linux内存管理:内存描述之高端内存

    <Linux内存管理:内存描述之内存节点node> <Linux内存管理:内存描述之内存区域zone> <Linux内存管理:内存描述之内存页面page> < ...

  7. 深入理解linux操作系统中的高端内存

    Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图.   Linux内核地址空间划分 通常32 ...

  8. linux 内核高端内存意义,Linux内核高端内存管理

    原先一直都对Linux高端内存的管理认识模模糊糊的,可能主要是初次接触Linux kernel 是0.11版吧,当初的内存设计是16M,Linus对拥有32M的内存都是觊觎万分,1G内存恐怕是天方夜谭 ...

  9. 【Linux】Linux的内核空间(低端内存、高端内存)

    内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点. 内核空间与用户空间的关系 在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法就 ...

最新文章

  1. Gazebo构建小车模型并通过ROS控制
  2. iPhone开发:Objective-c中@property声明时的参数释疑
  3. python获取输入数字_python获取从命令行输入数字的方法
  4. 【HAOI2015】树上染色
  5. Flurl使用Polly实现重试Policy
  6. mysql主从虚拟机_虚拟机centos7Mysql实现主从配置
  7. 【Elasticsearch】 es 排查问题 explain 使用 内容解释
  8. 在UAP中如何通过WebView控件进行C#与JS的交互
  9. SLAM之g2o安装
  10. linux yum 五笔输入法,CentOS 7 安装五笔输入法
  11. 文献翻译——基于关联规则挖掘识别的鸡源大肠杆菌共有多重耐药模式(下)
  12. excellvba引用计算机用户名,EXCEL VBA 取当前登录 用户名的多种实现方法
  13. python入门系列(4) -- python常见应用
  14. 怎么将抖音上的多个视频合成一个视频
  15. (保姆级)国内1块钱注册火爆全网的OpenAI-ChatGPT机器人
  16. JAVA 实现《布谷鸟闯关-简单版》游戏
  17. 微信公共号分享链接配置
  18. 华为南研所提前批面试(2015年8月22日)
  19. 不破坏背景的情况下在线ps替换文字
  20. LeetCode 208 实现 Trie (字典树)

热门文章

  1. 【程序】Marvell 88W8801 WiFi模块连接路由器,并使用lwip2.0.3建立http服务器(20180807版)
  2. 产业区块链一周动态丨蚂蚁集团计划上市,苏州成立10亿元区块链基金
  3. av_find_best_stream
  4. 实际应用和量子计算的实现
  5. c语言pow函数精度差,pow()函数结果强制转化为int造成误差的分析
  6. root用户执行sourc /etc/profile命令提示权限不够
  7. OV7670手册相关摘要
  8. 互斥事件的概念和公式_2014-2015学年高二数学课件:《互斥事件的概率和加法公式》(湘教版必修五)...
  9. 《隐秘的角落》里笛卡尔的爱情故事,是真的吗?
  10. 怎么用python破解wifi密码?