2014年7月10日星期四

java设计模式 - 北风小轩

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
java设计模式 - 北风小轩  阅读原文»

Java设计模式-访问者模式

http://edu.ibeifeng.com/view-index-id-296.html

Java设计模式-迭代模式

http://edu.ibeifeng.com/view-index-id-295.html

Java设计模式-组合模式

http://edu.ibeifeng.com/view-index-id-128.html

Java设计模式-状态模式

http://edu.ibeifeng.com/view-index-id-127.html

Java设计模式-装饰模式

http://edu.ibeifeng.com/view-index-id-126.html

Java设计模式-中介者模式

http://edu.ibeifeng.com/view-index-id-125.html

Java设计模式-职责链模式

http://edu.ibeifeng.com/view-index-id-124.html

Java设计模式-原型模式

http://edu.ibeifeng.com/view-index-id-123.html

Java设计模式-享元模式

http://edu.ibeifeng.com/view-index-id-122.html

Java设计模式-适配器模式

http://edu.ibeifeng.com/view-index-id-120.html

Java设计模式-外观模式

http://edu.ibeifeng.com/view-index-id-121.html

Java设计模式-桥接模式

http://edu.ibeifeng.com/view-index-id-119.html

Java设计模式-模板方法模式

http://edu.ibeifeng.com/view-index-id-118.html

Java设计模式-命令模式

http://edu.ibeifeng.com/view-index-id-117.html

Java设计模式-解释器模式

http://edu.ibeifeng.com/view-index-id-116.html

Java设计模式-建造者模式

http://edu.ibeifeng.com/view-index-id-115.html

Java设计模式-简单工厂模式

http://edu.ibeifeng.com/view-index-id-114.html

Java设计模式-观察者模式

http://edu.ibeifeng.com/view-index-id-113.html

Java设计模式-工厂模式在开发中的运用

http://edu.ibeifeng.com/view-index-id-112.html

Java设计模式-工厂方法模式

http://edu.ibeifeng.com/view-index-id-111.html

Java设计模式-访问者模式

http://edu.ibeifeng.com/view-index-id-110.html

Java设计模式-迭代模式

http://edu.ibeifeng.com/view-index-id-109.html

Java设计模式-单例模式

http://edu.ibeifeng.com/view-index-id-108.html

Java设计模式-代理模式

http://edu.ibeifeng.com/view-index-id-107.html

Java设计模式-抽象工厂模式

http://edu.ibeifeng.com/view-index-id-106.html

Java设计模式-策略模式

http://edu.ibeifeng.com/view-index-id-105.html

Java设计模式-备忘录模式

http://edu.ibeifeng.com/view-index-id-104.html

手机APP同步观看

http://www.ibeifeng.com/appdown.html

扫一扫,下载北风手机客户端


本文链接:java设计模式,转载请注明。

【读书笔记::深入理解linux内核】内存寻址 - 李可以  阅读原文»

我对linux高端内存的错误理解都是从这篇文章得来的,这篇文章里讲的

物理地址 = 逻辑地址 – 0xC0000000:这是内核地址空间的地址转换关系。

这句话瞬间让我惊呆了,根据我的CPU的知识,开启分页之后,任何寻址都要经过mmu的转换,也就是一个二级查表的过程(386)

难道内核很特殊,当mmu看到某个逻辑地址是内核传来的之后,就不查表了,直接减去0xC0000000,然后就传递给内存控制器了???

我发现网上也有人和我问了同样的问题,看这个问题

这句话太让人费解了,让人费解到以至于要怀疑人生了,难道我过去所有学习到的知识全是错的?

以至于我们就开始胡思乱想了,“那么内核寻址的时候是怎么处理的,是把分页关了,还是用其他的方法绕过去的。

是啊,我们好聪明,聪明到开始怀疑,内核想要实现这个简单的相减关系是不是进内核就把分页关了,或者,有某些牛叉的,我们不知道的方法绕过分页机制??

不然TMD我们怎么理解这句话?

去看书吧,看看《深入理解linux内核》吧,翻到75页,看那么一段话:

“宏__pa用于把从PAGE_OFFSET开始的线性地址转换成相应的物理地址,而宏__va做相反的转换。”

#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))

代码一旦出来,看来一切都不用争论了,毕竟代码说明一切啊,然而这是事实嘛?

http://bbs.csdn.net/topics/100049760 有这个问题的人也不少,以至于人们开始争论起来了。

看完这篇帖子之后,我的内心开始鉴定了一些东西。

误解,这里一定有一个很大的误解,这个很大的误解就来源于,把linux的内存寻址和linux的内存管理搞混了。

第一:内核寻址肯定是经过页表转换的,页全局目录在编译时候静态初始化,768项到1023项(这决定了线性地址的3g到4g的范围)被映射到了0到1g的地方。

任何3g-4g的地址空间的地址(先不考虑高端内存)经过页表转换后就是0-1g的地址空间。但是TMD的是这个关系,但是说的好像不要经过页表转换似得。

第二:内核的宏__pa和__va有什么用呢?用在哪里?

于是我盯着unsigned long phys_addr这个东西使劲看,使劲看,我看了大半夜忽然明白,这代码里到处都是。。。(哈哈)

phys_addr是个变量,是个unsigned long的变量,变量吗,都有地址,我们假设这个地址是0xC0004323,这个地址的内容是0x0000ff3e

0xC0004323: 0x0000ff3e

我们让eax = phys_addr了,于是eax等于0x0000ff3e了,可是我们想访问这个地址的值,怎么办啊?

只有先获得va,把eax+0xc000_0000,然后在进行内存访问,经过页表转换后,传递给内存控制器的地址正好是0x0000ff3e,我们也正好能访问这个地址的值。

而假如把0x0000ff3e交给mmu,经过页表转换后,我们就不知道是什么东西了。

想通了之后又两个感慨,一是,unsigned long phys_addr不是指针胜似指针啊。第二个感慨是原来va和pa的用途在这里。

在把“宏__pa用于把从PAGE_OFFSET开始的线性地址转换成相应的物理地址,而宏__va做相反的转换。”这句话评论成瞎扯淡之后,整章我理解通了。

我随便找了一个内核函数

/*
* Change the memory type for the physial address range in kernel identity
* mapping space if that range is a part of identity map.
*/
int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
{
unsigned
long id_sz;

if (base > __pa(high_memory-1))
return 0;

/*
* some areas in the middle of the kernel identity range
* are not mapped, like the PCI space.
*/
if (!page_is_ram(base >> PAGE_SHIFT))
return 0;

id_sz
= (__pa(high_memory-1) <= base + size) ?
__pa(high_memory)
- base :
size;

if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
printk(KERN_INFO
"%s:%d ioremap_change_attr failed %s "
"for [mem %#010Lx-%#010Lx]\n",
current
->comm, current->pid,
cattr_name(flags),
base, (unsigned long long)(base + size-1));
return -EINVAL;
}
return 0;
}

我们首先要明白,要想获得base的值和high_memory的值,肯定是经过页表转换,访问内存才能得到值啊。

然而这个值恰好是地址而已,对这个值,进行pa,va转换,然后访问内存,看到这里,懂了吧。


本文链接:【读书笔记::深入理解linux内核】内存寻址,转载请注明。

阅读更多内容

没有评论:

发表评论