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.读一个 ...
随机推荐
- Android新版本SDK打开旧版本项目报错解决
1.Description Resource Path Location Type Unable to resolve target 'android-19 解决:打开project.properti ...
- 用paint 计算字符串的像素宽度
方法1: //直接返回参数字符串所占用的像素宽度 Paint paint = new Paint(); width = paint.measureText(str); 有一些view可以直接得到pai ...
- 自定义View(2)canas绘制基本图形的示例
效果 代码: void drawSample(Canvas canvas) { /* * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawP ...
- BZOJ 2301 Problem b(莫比乌斯函数)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2301 题意:每次给出a,b,c,d,K.求有多少数对(x,y)满足a<=x< ...
- POJ 2409 Let it Bead(polay计数)
题目链接:http://poj.org/problem?id=2409 题意:给出一个长度为m的项链,每个珠子可以用n种颜色涂色.翻转和旋转后相同的算作一种.有多少种不同的项链? 思路: (1) 对于 ...
- poj3207 Ikki’s Story IV – Panda’s Trick
2-SAT. tarjan缩点.强连通分量的点要选一起选. #include<cstdio> #include<algorithm> #include<cstring&g ...
- Toast 用于一个页面有多个提示
private Toast mToast; 2 初始化 mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT); 3 方法 priv ...
- libogg.so fro android编译方法
在网站下载源代码http://www.xiph.org/downloads/ 解压然后打开cygwin配置 CXX=arm-linux-androideabi-g++.exe LD=arm-linux ...
- Linux Shell编程(1): 条件语句
1.if—then#!/bin/bashif date 如果命令运行成功(退出码为0),则then部分的命令被执行then echo "good"fi ...
- 《C++ Primer 4th》读书笔记 第5章-表达式
原创文章,转载请注明出处: http://www.cnblogs.com/DayByDay/p/3912114.html