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.读一个 ...
随机推荐
- player/stage 学习---安装
环境 ubuntu 14.04 一,工具安装 sudo apt-get install git cmake g++ fltk1.1-dev libjpeg8-dev libpng12-dev libg ...
- Spring 操作数据库
试了一下spring的JdbcTemplate觉得很好用.首先增加一个连接到mysql数据库的dataSource <bean id="dataSource2" class= ...
- 数组 寻找最大的第k个数
int Partion(int asy[],int begin,int end) { int k=begin; int key=asy[end]; for(int i=begin;i<=end; ...
- ios进度条Demo一个
一个很简单的Dmo.就拿出来分享一下. 一个简单的阴影效果 _progressView.frame = CGRectMake(size.width * progress-size.width, H_H ...
- hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10
题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 最后的差确定,只需要计算和的种类 ...
- HDU 4948
题目大义: 给一张图,任意两点间有单向边,找出一种方案,使得每个新入队的点与队中的点距离<=2. 题解: 贪心,从最后入队点开始反向插入,每次找出最大入度的点入队. 只需证明最大入度点A与所有未 ...
- 函数fsp_try_extend_data_file
扩展表空间 /***********************************************************************//** Tries to extend t ...
- WPF 用 DataTemplate 合并DataGrid列表列头<类似报表设计>及行头列头样式 - 学习
WPF中 DataGrid 列头合并,类似于报表设计.效果图如下↓ 1.新建一个WPF项目WpfApplication1,新建一个窗体DataGridTest,前台代码如下: <Window x ...
- BZOJ2229: [Zjoi2011]最小割
题解: 真是一道神题!!! 大家还是围观JZP的题解吧(网址找不到了...) 代码: #include<cstdio> #include<cstdlib> #include&l ...
- Java Web编程的主要组件技术——Hibernate入门
参考书籍:<J2EE开源编程精要15讲> Hibernate是对象/关系映射(ORM,Object/Relational Mapping)的解决方案,就是将Java对象与对象关系映射到关系 ...