1. 读写内存的安全性
物理内存本身是不限制访问的,任何地址都可以读写,而操作系统要求不同的页面具有不同的访问权限,这是利用CPU模式和MMU的内存保护机制实现的。例如,Text Segment被只读保护起来,防止被错误的指令意外改写,内核地址空间也被保护起来,防止在用户模式下执行错误的指令意外改写内核数据。这样,执行错误指令或恶意代码的破坏能力受到了限制,顶多使当前进程因段错误终止,而不会影响整个系统的稳定性。
2,虚拟内存管理最主要的作用是让每个进程有独立的地址空间(进程间的安全)
所谓独立的地址空间是指,不同进程中的同一个VA被MMU映射到不同的PA,并且在某一个进程中访问任何地址都不可能访问到另外一个进程的数据,这样使得任何一个进程由于执行错误指令或恶意代码导致的非法内存访问都不会意外改写其它进程的数据,不会影响其它进程的运行,从而保证整个系统的稳定性。另一方面,每个进程都认为自己独占整个虚拟地址空间,这样链接器和加载器的实现会比较容易,不必考虑各进程的地址范围是否冲突。
现在我们也可以理解为什么共享库必须是位置无关代码了。比如libc,不同的进程虽然共享libc所在的物理页面,但这些物理页面被映射到各进程的虚拟地址空间时却位于不同的地址,所以要求libc的代码不管加载到什么地址都能正确执行。
3,VA到PA的映射会给分配和释放内存带来方便
物理地址不连续的几块内存可以映射成虚拟地址连续的一块内存。比如要用malloc分配一块很大的内存空间,虽然有足够多的空闲物理内存,却没有足够大的连续空闲内存,这时就可以分配多个不连续的物理页面而映射到连续的虚拟地址范围。
4,一个系统如果同时运行着很多进程,为各进程分配的内存之和可能会大于实际可用的物理内存,虚拟内存管理使得这种情况下各进程仍然能够正常运行
因为各进程分配的只不过是虚拟内存的页面,这些页面的数据可以映射到物理页面,也可以临时保存到磁盘上而不占用物理页面,在磁盘上临时保存虚拟内存页面的可能是一个磁盘分区,也可能是一个磁盘文件,称为交换设备(Swap Device)。当物理内存不够用时,将一些不常用的物理页面中的数据临时保存到交换设备,然后这个物理页面就认为是空闲的了,可以重新分配给进程使用,这个过程称为换出(Pageout)。如果进程要用到被换出的页面,就从交换设备再加载回物理内存,这称为换入(Pagein)。换出和换入操作统称为换页(Paging)
因此:
系统中可分配的内存总量 = 物理内存的大小 + 交换设备的大小
以下均转自Android游戏编程入门经典,转载请标明出处
通过使用glColor4f()为所有的顶点设置一个全局默认颜色。但有时需要更多细粒度的控制(例如,需要为每个顶点设置颜色)。
OpenGL ES提供这样的功能,需要的只是将RGBA浮点分量加到每个顶点,并告诉OpenGL ES在哪里可以找到每个顶点的颜色。
int VERTEX_SIZE = (2 + 4) * 4; ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE); byteBuffer.order(ByteOrder.nativeOrder()); vertices = byteBuffer.asFloatBuffer(); vertices.put(new float[]{ 0.0f, 0.0f, 1, 0, 0, 1, 319.0f, 0.0f, 0, 1, 0, 1, 160.0f, 479.0f, 0, 0, 1, 1 });
每个顶点需要两个坐标和4个(RGBA)颜色分量,因此一共需要6个浮点数。每个浮点数占4个字节,也就是说,一个顶点需要24个字节。当调用ByteBuffer.allocateDirect()方法时,只需把顶点数乘以VERTEX_SIZE就可得到需要的ByteBuffer空间。
如果需要渲染它,就必须告诉OpenGL ES这些顶点不但有位置信息,还有颜色属性。
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
现在OpenGL ES知道它可以得到每个顶点的位置和颜色信息,还需要告诉它从哪里可以获得这些信息:
vertices.position(0); gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); vertices.position(2); gl.glColorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
首先设置FloatBuffer的位置。FloatBuffer从0开始保存这些顶点。这个位置指向缓冲区第一个顶点的x坐标。接下来调用glVertexPointer()方法。唯一与前面实例不同的地方是这里需要指明顶点的大小(以字节为单位)。OpenGL ES将从指定的缓冲区的起始位置读取顶点位置。第一个顶点位置的地址增加VERTEX_SIZE字节后得到第二个顶点位置的地址,以此类推。
接下来,设置第一个顶点的R颜色分量在缓冲区中的位置并调用glColorPointer()方法,该方法告诉OpenGL ES在哪里可以找到顶点的颜色。第一个参数是每个颜色的分量数。分量数一直是4.第二个参数指明每个分量的类型,用GL10.GL_FLOAT来声明每个颜色分量都是浮点型,并且取值范围是0~1.第三个参数是顶点颜色间的步长。最后一个参数是顶点缓冲区。
只要在调用glColorPointer()之前调用vertices.position(2),OpenGL ES就会知道第一个顶点的颜色是从缓冲区中的第三个浮点数开始的。如果位置不设为2,OpenGL ES将从位置0开始读取颜色值。
package org.example.androidgames.glbasics; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import org.example.androidgames.framework.Game; import org.example.androidgames.framework.Screen; import org.example.androidgames.framework.impl.GLGame; import org.example.androidgames.framework.impl.GLGraphics; public class ColoredTriangleTest extends GLGame{ @Override public Screen getStartScreen() { // TODO Auto-generated method stub return new ColoredTriangleScreen(this); } class ColoredTriangleScreen extends Screen { final int VERTEX_SIZE = (2 + 4) * 4; GLGraphics glGraphics; FloatBuffer vertices; public ColoredTriangleScreen(Game game) { super(game); glGraphics = ((GLGame)game).getGLGraphics(); ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE); byteBuffer.order(ByteOrder.nativeOrder()); vertices = byteBuffer.asFloatBuffer(); vertices.put(new float[]{ 0.0f, 0.0f, 1, 0, 0, 1, 319.0f, 0.0f, 0, 1, 0, 1, 160.0f, 479.0f, 0, 0, 1, 1 }); } @Override public void update(float deltaTime) { // TODO Auto-generated method stub } @Override public void present(float deltaTime) { // TODO Auto-generated method stub GL10 gl = glGraphics.getGL(); gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight()); gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrthof(0, 320, 0, 480, 1, -1); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); vertices.position(0); gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); vertices.position(2); gl.glColorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, vertices); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); } @Override public void pause() { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } } }
运行效果如下:
这个应该用的蛮多的,为啥中文没有例子呢?
两个selectfield,第一个在change事件里面修改第二个的store就可以了
{
xtype:'selectfield',
label:'入学年份',
displayField:"startyear",
valueField:"startyear",
listeners:{
change: function(selectbox,newValue,oldValue)
{
var comboCity = Ext.getCmp('classno');
var store = comboCity.getStore().filter('startyear', this.getValue());
}
}
},
{
xtype:'selectfield',
id:'classno',
label:'选择所在班级',
store:'ClassStore',
displayField:"classno",
valueField:"classno",
},