linux内核地址mapping
linux内核采用页式存储管理,虚拟地址空间划分成固定大小的页面,由MMU(memory manager unit)在运行时将virtual address mapping to (或者说是变化成)某个物理内存页面中的地址;同段式存储管理相比,页式存储管理有不少的优势
page size 固定 const,便于管理;
当要将一部分物理空间的内容换到磁盘上的时候,在段式内存存储管理中要将整个段都换出(通常的每个段都是很大的);而在page storage manager中则是按页进行;
页式存储管理与段式存储管理所要求的硬件支撑不同,一种CPU既然支撑页式存储管理,就无需再支持段式存储管理了,当i386很特殊,需特别对待;
由于i386系列的历史演变过程,它对页式存储管理的支持是在其段式存储管理已经存在 相当的时间才发展起来的,i386程序不管程序 怎么写,一律对程序中石油的地址先进行段式mapping,再进行page math mapping;既然CPU的硬件结构如此这般,Linux内核也只好服从Intel;这样的双重映射起始是毫无必要的,也使mapping 的过程变的更加的复杂,不易理解;
总结真实的段式内存管理仅需在i386上实现,对于M68k,powerpc根本则不存在段式映射这一层,但请注意,不管是神马操作系统UNIX也不例外,只要在i386上的实现,就必须至少在实现上要先经过段式内存的mapping;
linux objdump实用工具时很有用的,可以用来实现反汇编binary;
保护模式下段寄存器format;
TI(table Indicator,0=GDT-global describe table,1=LDT-local..)
RPL-Request Privilge level;
Intel的涉及意图是用内核用GDT,其它的进程用其各自的LDT,最低2位RPL(Request Privilge level)为所要求的特权级别;
内核在建立一个进程时都要将其段寄存器设置好;
linux kernel基本上不使用局部描述表LDT,LDT只是在VM86模拟中运行wine以及其他在linux上模拟运行windows软件或dos软件的程序中财使用;
RPL(Request Privileges level) 内核为0级用户(process)为3;
/*
*This contains typically 140 quadwords,depending on NR_CPUS.
*
*NOE!Make sure the gdt descriptor in head.S matchs this if you change anything.
entry(gdt-global destributed table)
.quad NULL descriptor
段式映射(segment mapping)过程中所有进程全部都共用一个GDT global descriptor table;在页式映射机制mechanism每个进程都有其自身的page directory;
指向这个目录的指针保持在每个进程的mm_struct 数据结构中,每当调度schedule一个进程进入内核运行的时候,内核都要为即将运行的进程设置好控制
寄存器control register,而MMU的硬件则总是从CR3中取得指向当前页面目录的指针;CPU在执行程序时使用的是虚地址,而MMU硬件在进行映射时所用的则是物理地址;
static inline void switch_mm(struct mm_struct *prev,struct mm_struct *next,struct task_struct *tsk,unsigned cpu)
{
.............
asm volatile("movl %0,%%cr3": : "r" (__pa(next->pgd)));
}
在页式映射过程中,i386 CPU需要访问内存3次;
第一次是page directory
第二次是page table
第三次测试target;
虚拟存储的的高效实现有赖于高速缓存;
除常规的页式映射,为了能在linux内核上仿真运行段式存储管理的windows或dos软件,特别的提供了2个特殊的,与段式存储管理有关的系统调用;
modify_ldt(local descriptor table)(int func,void *ptr,unsigned bytecount)
此system call可以用来改变当前进程的局部段描述表,
在free software foundation下,除了linux外还有多个项目,其中一个叫"WINE",来源于"Windows Emulation",目的是在linux上仿真运行windows软件.
struct modify_ldt_ldt_s {
unsigned int entry_number;
unsigned long base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
}
从上可以看出此段式存储管理涉及到的系统调用无疑是在内核管理机制上挖了个洞!既然一个进程可以改变它的局部段描述表,同样也可以设法侵犯到其他进程或内核的空间
,但是只要不让用户进程掌握修改page dir and page table;
vm86(struct vm86_struct *info)
此系统调用用来在linux上模拟dos软件,i386 CPU专门提供了一种寻址方式VM86,用来在保护模式下模拟运行实模式(real-mode);
目的是为采用保护模式的系统(windows,os/2)提供与real-mode software(real dos)兼容性 compatibility;
linux内核中几个重要的数据结构和函数;
form hardware angle sayin:linux内核只要能 cable for hardware准备好页面目录PGD,页面表PT以及全局段描述表GDT和局部段描述表LDT,并正确地设置有关的寄存器,就完成了内存管理机制中地址地址映射部分的准备工作;
虽然最终的目的是地址映射,但是实际上内核所需要做的管理工作却是复杂很多.
在于内存管理有关的代码中有几个数据结构是很重要的,这些数据结构及其使用构成了代码中内存管理的基本框架
页面目录PGD,中间目录PMD和页面表PT分别是由pgd_t,pmd_t以及pte_t构成 的数组,而这些表项又都是数据结构
/**
*These are used to make use of C type-checking..
*/
#if CONFIG_X86_PAE physical address extension;
typedef struct {unsigned long pte_low,pte_high;} pte_t--指的是也表 ;
typedef struct {unsigned long long pmd;} pmd_t;
typedef struct {unsigned long long pgd;} pgd_t;
#define pte_val(x) ((x).pte_low | ((unsigned long long)|(x).pte_high << 32 ))
#else
linux内核地址mapping的更多相关文章
- U-boot mkimage指定Linux内核地址时的两种方式
http://blog.csdn.net/embededswordman/article/details/6704197 uImage的制作是使用的u-boot工具mkimage,build完u-bo ...
- Lab1:Linux内核编译及添加系统调用(详细版)
实验一:Linux内核编译及添加系统调用(HDU) 花了一上午的时间来写这个,良心制作,发现自己刚学的时候没有找到很详细的,就是泛泛的说了下细节地方也没有,于是自己写了这个,有点长,如果你认真的看完了 ...
- Linux内核监控模块-2-系统调用表地址的获取(Linux内核版本3.13)
那么在Linux内核2.6之后,不能直接导出sys_call_table的地址后,我们要如何获得系统调用表的地址,从而实现系统调用的截获呢. 先贴上我实现好的代码,然后再来讲解吧. modu.c #i ...
- ARM linux内核启动时几个关键地址【转】
转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1. 内核启动地址1.1. 名词解释ZTEXTAD ...
- LINUX 内核文档地址
Linux的man很强大,该手册分成很多section,使用man时可以指定不同的section来浏览,各个section意义如下: 1 - commands2 - system calls3 - l ...
- oracle-linux7 镜像地址 secuCRT 注册-linux内核
http://mirrors.dotsrc.org/oracle-linux/OL7/u4/x86_64/ secuCRT 注册 https://github.com/hanxianzhai/Secu ...
- Linux内核启动过程概述
版权声明:本文原创,转载需声明作者ID和原文链接地址. Hi!大家好,我是CrazyCatJack.今天给大家带来的是Linux内核启动过程概述.希望能够帮助大家更好的理解Linux内核的启动,并且创 ...
- 《Linux内核设计与实现》课本第十八章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第十八章自学笔记 By20135203齐岳 通过打印来调试 printk()是内核提供的格式化打印函数,除了和C库提供的printf()函数功能相同外还有一 ...
- Linux内核同步机制--转发自蜗窝科技
Linux内核同步机制之(一):原子操作 http://www.wowotech.net/linux_kenrel/atomic.html 一.源由 我们的程序逻辑经常遇到这样的操作序列: 1.读一个 ...
随机推荐
- 关于fft的一点总结
好吧,其实我并没有深入运用fft,只会优化卷积 听说fft经常和生成函数结合在一起………………oi真是迅猛发展,我真是与时代脱节了…… 关于fft的学习推荐直接去看算法导论,写得非常清楚 主要弄懂n次 ...
- WebClient+Fiddler2完美搭配下载远程页面信息
WebClient可以下载远程页面信息,这个大家应该都知道,核心代码如下: WebClient web = new WebClient(); string url = String.Format(&q ...
- 终极解决方案:windows10开机黑屏,死机
windows10开机黑屏,死机一般情况都是由于双显卡中的独立显卡驱动造成的! 那么试着升级一下你的BIOS吧!一定要在官网下载你对应的BIOS驱动,然后双击安装,这个时候就别再动机子了,让他自己刷新 ...
- VS2010解决方案不显示无法添加项目问题
问题:在VS2010中不显示解决方案,导致不能添加项目. 方法:工具-选项-项目和解决方案-选中“总是显示解决方案”,ok
- CentOS6.2下fastDFS的完整安装和配置步骤
centos6.2系统下安装配置FastDFS步骤: 1:安装libevent(libevent-2.0.16-stable) ##卸载系统自带libevent rpm -qa|grep libeve ...
- [反汇编练习] 160个CrackMe之007
[反汇编练习] 160个CrackMe之007. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- ORACLE 如何定位消耗资源的SQL
在分析SQL性能的时候,经常需要确定资源消耗多的SQL,总结如下: 1 查看值得怀疑的SQLselect substr(to_char(s.pct, '99.00'), 2) || '%' load, ...
- 【转】 IOS中定时器NSTimer的开启与关闭
原文网址:http://blog.csdn.net/enuola/article/details/8099461 调用一次计时器方法: myTimer = [NSTimer scheduledTime ...
- 如何寻找设计灵感?写给刚入行的设计师(转自UI中国)
如何寻找设计灵感?写给刚入行的设计师 如何寻找设计灵感? 这一次的文章,我想和大家聊聊年轻的设计师在没有那么多经验的情况下如何寻找设计师灵感.(希望这篇文章也能帮助感同身受的你) 每个设计师对设计都有 ...
- mysql 自旋锁
自旋(spin)是一种通过不间断地测试来查看一个资源是否变为可用状态的等待操作,用于仅需要等待很短的时间等待所需资源的场景.使用自旋这种“空闲循环(busy-loop)”来完成资源等待的方式要比通过上 ...