标签:self 映射 com 没有 不能 return lseek 结果 main
一、Linux上地址映射:
1、逻辑地址:由程序产生的和段相关的偏移地址部分
线性地址:是逻辑地址到物理地址变换的中间层,程序代码会产生逻辑地址,段中的偏移地址加上相应段的基地址就生成了一个线性地址。在Intel 80836的线性地址空间从0x00 00 00 00----0xff ff ff ff,为2^32次方,就是4G大小。
物理地址:指出目前CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。
2.实模式和保护模式的区别:
实模式将整个物理内存看成分段区域,程序的代码和数据位于不同区域,系统程序和用户程序没有区别对待,而且每一个指针都是指向实在的物理地址。不能使用多线程,不能实现权限分级
保护模式包括权限分级,内存分页,多任务等功能
3.从逻辑地址到线性地址的转化:
DS段选择符:
GDTR指向GDT表,指明是标的哪一项
在Linux系统中所有的段起始地址都是0x 00 00 00 00
所以Linux中逻辑模式和线性模式的地址相同。
将线性地址转化为物理地址:
将32位地址分为三部分:
前10位:0-1023个值,表示在页目录表里找到指向的哪个页表
中间10位:0-1023个值,指定在页表里的哪一项,在真实的地址里用的是哪一个页框;
后12位:表示在页里的偏移
在Linux里面cd /proc/pid/pagemap允许用户态的进程查看每个虚拟页映射到的物理页,一共8个字节64个位,0-55位转化为十进制用来表示物理页号,第63位0表示不在内存中,1表示在内存中,可以用cat status查看,要找到当前进程的pid,有一个self链接文件,直接链接到当前进程的pid,即就是/proc/self/pagemap;
在Linux中实现的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<stdint.h>
#include<assert.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
int mem_addr(unsigned long vaddr,unsigned long *phy)
{
int pagesize = getpagesize();
unsigned long v_index = vaddr/pagesize;
unsigned long v_offset = v_insex * sizeof(uin64_t);
unsigned long page_offset = vaddr%pagesize;
uin64_t item = 0;
int fd = open("/proc/self/pagemap",O_RDONLY);
if(fd == -1)
{
printf("open pagemap error\n");
return ;
}
if(lseek(fd,v_offset,SEEK_SET)==-1)
{
printf("sleek error\n");
return ;
}
if(read(fd,&item,sizeof(uint64_t)) != sizeof(uint64_t))
{
Printf(“read item error\n”);
return;
}
if((((uin64_t)1<<63)&item)==0)
{
printf("flg faild\n");
return ;
}
uin64_t phy_index = (((uin64_t)1<<55)-1)&item;
*phy = phy_index * pagesize + page_offset;
}
int main()
{
int a = 0;
int addr = 0;
mem_addr(&a,&addr);
}
测试:数据段值改变,代码段值不变
局部变量:a = 0,addr = 0; 线性地址不变,物理地址改变
全局变量:int g = 0;线性地址不变,物理地址改变
函数:mem_addr(fun,addr);线性地址不变,物理地址不变;
堆区:fork()以后如果对子进程的内存不进行改变,物理地址不变,如果进行改变,物理地址也会改变。
二、斐波那契数列:
举例:1 1 2 3 5 8 13 21 34 55 89
所以F(11) = 89;
1.循环:
int fab(int n)
{
if(n == 1 || n == 2)
{
return 1;
}
int num1 = 1;
int num2 = 1;
int tmp = 0;
while (n-2)
{
tmp = num1;
num1 = num2;
num2 = num2 + tmp;
n--;
}
return num2;
}
2.递归:
int fab2(int n)
{
if (n ==1 || n == 2)
{
return 1;
}
else
return fab2(n-1)+fab2(n-2);
}
3.改进的循环
int fab3(int num1,int num2,int n)
{
if (n ==1 || n == 2)
{
return 2;
}
else
return fab3(num2,num1+num2,n-1);
}
标签:self 映射 com 没有 不能 return lseek 结果 main
原文地址:http://www.cnblogs.com/waiting999/p/7118912.html