内存系统(共12篇)
内存系统 篇1
0 引言
GNU/Hurd操作系统是GNU设计用来替代Unix内核的新一代操作系统内核[1]。Hurd系统是基于CMU的Mach3.0微内核架构,由GNU小组对其进一步开发完成,并由Debian公司进行发布。
Hurd采用Mach微内核作为其内核,Mach微内核完成最基本的操作系统功能,例如进程通信、内存管理、硬件管理等。Hurd是架设在Mach上的一组服务,这一组服务贯彻了传统操作系统概念,实现了文件系统,网络协议,文件的访问控制,以及其它的操作系统功能。
Hurd与Mach系统在特点上各有千秋,例如Hurd的模块化以及微内核架构特点、Mach独有的IPC通信和内存管理特点等。本文将简单介绍Hurd与Mach系统特点,并分析Mach微内核的内存管理与接口实现。最后,讨论在Mach微内核下内存共享的实现。
1 Hurd操作系统与Mach微内核
1.1 Hurd操作系统及其特点
Hurd操作系统是GNU项目组设计用来取代Unix的新一代操作系统。虽然目前不是最流行的操作系统,但因其拥有很多独特的特性,从而与其它的操作系统相比,表现着更为出众的使用优势。Hurd的优点如下[2]:
(1)Hurd是开源的操作系统。任何人都可以使用并且修改,由GNU小组进行维护。
(2)兼容性。Hurd提供了一个通用的编程环境和用户环境,是一个类Unix的内核。Hurd使用GNU C库,并且兼容ANSI/ISO,POSIX,X/Open等标准。
(3)易于设计与扩展。Hurd不同于其他流行的操作系统内核,而是面向对象的结构。这种结构使得Hurd在进行扩展和修改时,无需重写内核,只需要修改相应的模块。
(4)多服务。Hurd实现了多线程,可高效地运行在单处理器和多处理机上。Hurd的运行性能非常稳定,还是一个很好的学习平台,各种想法实现起来也非常便捷。
GNU Hurd设计成多服务的面向对象的操作系统。可将其视为一组对象的集合,对象扩展了底层微内核Mach的功能,可以实现标准的操作系统功能以及实践系统设定的各项策略。系统的服务是通过专门的对象来实现的,这些对象在用户态下被称为server。一个服务也可以分解为一些对象,比如文件系统服务可以分解为后备存储、文件属性以及目录等。Hurd可以视为基于微内核Mach的服务的集合,包括文件系统、网络协议以及其他一些系统功能。GNU Hurd多服务操作系统的时新评论均详细介绍了Hurd的系统架构以及Hurd实现的详细细节,同时也给出了Hurd系统的优点和缺点[3]。
1.2 Mach微内核及其特点
Hurd作为GNU的操作系统,架设在微内核Mach之上,实现了传统意义上的操作系统功能。Mach是第一代的微内核结构,是由CMU大学设计并实现的微内核。GNU对其进行了修改和扩充,因而形成了GNU Mach微内核,GNU Mach兼容CMU的Mach 3.0系统。
GNU Mach是GNU项目的微内核。Mach并不显现操作系统的特点,而是借助一个简单的可扩展通信内核、用户模式的任务来实现传统操作系统功能。Mach所提供的基本功能包括控制流的管理(threads)、资源分配(tasks)、支持虚拟地址空间、管理硬件资源(如处理器、物理内存)等[4]。另外,Mach还具有强大的内存管理和进程间通信的功能,这是操作系统的基础功能,也为Hurd的server、GNU C库和用户程序提供了底层基础功能。微内核Mach本身虽不提供操作系统的功能,却也使得Hurd的服务和C库在Mach上实现了一个满足POSIX标准的操作系统。文献[5]给出了Mach微内核的设计创意和详细实现细节。
2 Mach微内核的虚拟内存管理
通常,操作系统的内存管理部分主要完成空间分配、虚拟地址映射和地址保护等功能,从而使得系统安全高效地使用有限的存储空间。Mach微内核的内存管理机制设计目标是:
(1)支持较大的、松散的虚拟地址空间。
(2)灵活的内存保护机制。
(3)copy-on-write操作。
(4)任务间内存共享,包括copy-on-write和read/write内存共享。
(5)内存映射文件。
(6)用户模式提供页和对象的后备存储[6,7]。
Mach的内存管理在设计上尽可能地独立于硬件,对硬件的唯一要求是提供页式管理机制支持,并且对于页的大小也不作限制,所有这些化简了在移植时的操作,使得Mach能够支持许多不同的体系结构。
2.1 Mach内核的5个基本抽象
Mach是一个支持并行分布多体系结构的操作系统微内核,有5个最基本的抽象概念,这些抽象概念对于理解Mach以及Mach的虚拟内存管理机制是必不缺少的。这五个概念分别是任务(Task)、线程(Thread)、端口(Port)、消息(Message)、内存对象(Memory object)[8],对其分析如下:
(1)任务(Task)。每个task是一个线程运行的执行环境,是最基本的资源分配单位。通常,task包括虚拟地址空间和系统资源(处理器、虚拟内存等),与UNIX进程的概念相类似。
(2)线程(Thread)。Thread是CPU使用的基本单位,是程序执行的实体。同一个任务内的所有thread共享全部资源。
(3)端口(Port)。port是一个信息通道。通过信道,Mach可以安全地进行消息传递。
(4)消息(Message)。message是线程之间通信使用的数据对象的类型集合。message大小不限,并可能包含指针和类型。
(5)内存对象(Memory Object)。Memory object是由server管理和提供的可以映射到一个任务的地址空间的数据备份。这是一种对存储的抽象,可以用来表示例如文件等存储实体。
2.2 Mach虚拟内存管理
Mach最著名的设计之一是其中的虚拟内存的设计,Mach将虚拟内存系统分为机器独立和机器依赖两部分。机器依赖提供一个简单的接口,负责管理硬件地址映射表;机器独立除了提供逻辑页表的管理,还提供映射表所组成的内存区域概念,同时也提供内存对象的支持和接口实现。Mach虚拟内存系统除支持单处理器外,还支持共享内存的多处理器系统,同时也具有很好的移植性,可以在各种不同的系统架构下加载运行。高性能也是Mach重要特点之一。Mach提供很大的、宽泛的虚拟地址空间、共享内存以及虚拟内存拷贝优化等等。Mach的每个任务(task)均拥有较大的地址空间范围,包括内存区域以及内存区域所映射的内存对象。Mach内规定任务的地址空间只由底层硬件的寻址限制所决定。
2.2.1 虚拟地址空间(Virtual Address Spaces)
虚拟地址空间定义了一组地址,这组地址指示线程thread在任务task执行的虚拟地址。虚拟地址空间由其对应的task命名。Mach的任务都拥有很大的虚拟地址空间,其线程的执行就是在此虚拟地址空间中。
虚拟地址空间由松散的已经索引的内存页面集合组成。Mach内核按照页面的属性值将这些内存页面分成不同的组,将其称为内存区域(memory regions)。页面的属性包括继承属性、保护属性、后备的抽象内存对象等等。系统的各项操作和运行机制均是基于内存区域的,但是用户对于内存区域的使用却无需限制,用户可以尽其所需地扩张内存区域。同时,Mach内核也可以按照适合的方式自由地合并和分割内存区域,从client的视角看,虚拟内存空间就是一个页面的集合。调用vm_region可以获得内存区域的属性。尽管内存区域是存在于内核的概念,调用vm_map也可以修改内存区域的继承和保护属性。
任务的虚拟地址空间是在任务创建时分配完成的,并于任务结束时一并销毁。当任务刚刚创建时,其虚拟内存空间是空的,必须通过执行一定操作申请地址内存空间。通过task_create调用,子任务可以继承其父任务的内存区域。而vm_inherit调用则可以修改内存区域的继承属性值,这些属性值包括:
(1)VM_INHERIT_NONE—该内存区域在新任务中不会被定义。
(2)VM_INHERIT_COPY—该内存区域将会以copy优化的方式在新任务中进行创建。
(3)VM_INHERIT_SHARE—新旧任务将完全共享同一内存区域。在此,可以看出Mach提供了父子任务的内存共享。
内存区域的语义识别是通过a memory manager的行为实现的。当一个内存区域在虚拟空间中创立时,一个虚拟内存对象(memory object)便和该内存区域联系在一起了。内存对象将负责内存区域的后备数据存储,其语义实现是通过一个称为memory manager的任务实现的。内核中不存在直接操作内存区域的系统调用,任务是通过memory manager的函数或者向memory manager发送消息来完成操作的。
vm_map调用是确定任务内存区域的唯一方法,借此可以设定该内存区域的基本信息(例如内存中位置、大小、保护属性、继承属性等)。需要指出的是,最重要的参数是对其抽象内存对象的指定,因其提供了内存区域的后备存储。
图1是以client的角度呈现的虚拟内存结构图。图中显示了三个内存区域,其中的两个共有一个相同的后备对象存储memory object,但是两者的继承属性或者保护属性可以不相同。
2.2.2 内存对象(Memory Objects)
内存对象代表了非常驻内存的内存区域,内存对象是内存区域的后备存储。而实现内存对象概念的任务则称为memory manager。memory manager实现了内存对象的完整语义,并且提供了若干接口,以方便用户使用。
用户态的任务操作内存的通用过程是:一个任务确定其内存区域,并指定该内存区域的内存对象;任务访问该内存区域的某部分,假如该内存区域不在内存中,则发生缺页中断,将其换入后继续访问;假如数据已修改,则将数据存入内存对象中,再将其换出内存;销毁内存区域以及内存对象。
内核使用内存可以将内存作为内存对象内容的缓存(cache)。该cache的一部分是常驻内存的,将此部分内存对象称之为memory cache object。内核维护cache,并对其适时、合理地进行管理、填充和刷新。
2.3 Mach虚拟内存管理接口的实现
GNU Mach很大程度上兼容了CMU的Mach 3.0,这一点在接口的层面上已经清晰地显现出来。文献[8,9]分别是Mach 3.0和GNU Mach的接口使用手册,经过分析,两者大部分相同,只是GNU Mach的接口实现简化了CMU Mach的接口,还对其进行了一定的封装处理。
在虚拟内存管理上,两者均提供了较为丰富的接口,同时,一个任务也可以修改其地址空间,例如:在页边界上分配虚拟内存区域、删除虚拟内存区域、设置虚拟内存区域的保护属性、指定虚拟内存区域的继承属性、创建和管理内存对象,内存对象可以映射另一个任务的虚拟地址空间。
Mach亦设有各类功能接口以实现其虚拟内存管理,可将这些接口分为两大类:虚拟内存接口和外部存储管理接口。
对于虚拟内存接口,主要有内存分配和回收、数据传输(读、写和拷贝数据)、内存区域属性设置(继承、保护属性)、映射内存对象。其中,映射内存对象可以将一个任务的地址映射到另外一个任务的地址空间中去,可以实现不同任务的内存共享。这一接口设置屏蔽了内存对象的操作,用户使用起来就像直接操作内存一样。其好处是大大降低了用户管理存储空间的难度,但是也有相应的不足,就是不可以使用高级的内存共享操作。
外部内存接口主要是针对于内存对象的接口,主要有设置内存对象服务、删除内存对象、内存对象的数据传输、内存对象锁定和设置内存对象属性等几类接口。使用外部内存管理接口可以实现较为复杂的内存管理,也包括内存共享操作。
3 Hurd的内存共享
通过对Mach微内核的内存管理的研究,本文提出在Hurd下的几种内存共享方案。
(1)考虑Hurd下POSIX标准的内存共享方案。为了便于实验和对比,同时在Linux和Hurd下进行了实验。
(2)使用Mach的内存对象的概念完成内存共享。这是重点阐述的部分,使用Mach内存对象的概念,并同时使用其IPC通信功能,实现内存共享与映射。
(3)考虑添加系统调用的方法完成内存共享。
3.1 内存共享
首先,介绍一下内存共享的概念。内存共享是指共享内存,从字面意义解释,就是多个进程可以将同一段内存映射到各自的进程空间,以此来实现数据的共享以及传输,这也是进程间最快的一种通信方式,图2是内存共享的示意图。
3.2 使用POSIX标准实现内存共享
Hurd系统支持POSIX标准,而POSIX标准对于内存共享是有规定含义的,所以可在Hurd系统下尝试使用POSIX的内存共享。POSIX标准对于内存共享的实现有两种方法。
(1)内存映射文件(memory-mapped file)。由open函数打开此类文件,并由mmap函数将得到的描述字映射到当前地址空间。
(2)共享内存区对象(shared-memory object)。由shm_open函数打开POSIX标准的一个IPC对象,并且使用mmap函数将其映射到进程地址空间中。
为了验证Hurd系统对于POSIX标准的内存共享,下面分别在Linux系统和Hurd系统下作了实验。
Linux系统下的POSIX内存共享有两种方法。一种是mmap系统调用映射普通文件完成内存共享;另一种是,shm_open函数打开对象,并且使用mmap函数完成内存共享。对于第二种方法,在Linux目录中存在共享内存区对象的目录dev/shm/,在此目录下可以发现打开的共享对象,符合POSIX标准。
Hurd系统是支持POSIX标准的,所以可假设Hurd系统也应该支持POSIX标准的内存共享。现将Linux下的程序移植到Hurd系统下进行对比。实验后发现,在Hurd目录中不存在共享内存区对象的目录/dev/shm,也不存在目标文件。同时,在程序执行的目录下发现了一个文件,该文件内容为共享内存对象的内容。这种情况说明了该文件是存储在本地磁盘上的,不是内存中的共享对象,因而不符合POSIX标准。
由此,得出结论:对于POSIX标准的支持,Hurd系统并没有完全实现,只是使用了文件进行模拟而已。所以,Hurd系统下,使用POSIX标准的内存共享是不可行的。
3.3 使用Mach自身接口实现内存共享
使用微内核Mach自身的接口和机制完成内存共享,可分为这样几种情况,即同一任务的不同线程之间、有父子关系的任务之间、无关系任务之间完成内存共享。对于前两种情况都比较简单,而对于第三种情况,稍微有些复杂。对其叙述如下:
(1)对于同一任务的不同线程之间的内存共享。这是共享任务全部资源的,所以,两个不同的线程可以直接完成最大限度的内存共享。这是内存共享中最为简单的情况。
(2)对于父子关系的任务之间的内存共享。可以通过设置内存区域(memory region)的继承属性来实现。
(3)对于无关系任务之间的内存共享。可以通过内存对象(memory object)和内存映射文件完成内存共享。本文将使用Mach微内核的内存管理以及内存对象(memory object)概念,完成内存共享。在Mach微内核中,结合Mach的IPC、Mach对于内存基本操作以及Mach对于内存对象的支持这三个方面的内容,即可完成内存共享的要求。整体思路是:首先建立共享的内存对象,设置内存对象属性,将内存对象映射到相应任务的地址空间,然后完成相应的访问,最后销毁内存对象。需要注意的是,在这一过程中,关键问题是实现任务间的交互、内存对象的保护和共享。
3.4 添加新的系统调用完成内存共享
虽然Hurd支持POSIX标准,但是对于内存共享并没有完全支持,在以后的版本中也可能会对其给予相应的支持。鉴于POSIX的内存共享标准,也可以在Hurd上实现符合POSIX标准或者其他形式的内存共享。这种实现则需要参考Linux和Mac OS的系统调用方式。
添加新的系统调用来实现内存共享的方法,需要添加至少两个系统调用,一个是内存区域的分配,另一个是内存区域的回收。详情请参考Mac OS的系统调用添加方式,这里就不再赘述了。
4 结束语
本文介绍了Hurd操作系统与Mach微内核,并解释了两者之间的关系,分别讲述了两者的特点和优点。着重阐述了微内核Mach的虚拟内存管理机制,并且分析其实现虚拟内存管理功能的接口实现。最后,给出了在GNU Hurd系统下的几种内存共享方法。经过实验分析,Hurd系统下POSIX标准的内存共享方法是不可行的,Hurd对于POSIX的标准没有达到完全兼容。而使用Mach内核自身的内存对象的概念可以实现内存共享,可以完成多种形式的内存共享,效果也十分理想,因而是一种很好的方法。另外,也可以考虑在Hurd下添加系统调用来完成内存共享。
参考文献
[1]GNU/Hurd[OL].http://www.gnu.org/software/hurd/hurd/doc-umentation.html
[2]BUSHNELL,THOMAS.The GNU Hurd Reference Manual[M].2007-11.
[3]WALFIELD N H,BRINKMANN M.A critique of the GNU H-urd multi-Server operating system[J].ACM SIGOPS Operatin-g Systems Review,2007.
[4]BRINKMANN,MARCUS.The GNU Mach reference manual[M].Free Software Foundation,2008-11.
[5]ACCETTA M,BARON R,BOLOSKY W.Mach:a new kernelfoundation for UNIX[J].Carnegie Mellon University.Citeseer,39(4864):1-16.
[6]RASHID,TEVANIAN R.Machine-independent virtual memo-ry management for paged uniprocessor and multiprocessor archi-tectures[J].IEEE Transactions on Computers,1988,37:896-908.
[7]王永杰,战超.MACH操作系统内存管理[J].计算机研究与发展,1992(10):27-30.
[8]BRINKMANN,MARCUS.Mach 3 Kernel Principles[M].Free S-oftware Foundation,2008:37-54.
[9]BRINKMANN,MARCUS.Mach 3 kernel interfaces[M].Free S-oftware Foundation,2008:73-150.
内存系统 篇2
内存的用户空间和内核空间:
Linux虚拟内存的大小为2^32(在32位的x86机器上),内核将这4G字节的空间分为两部分。最高的1G字节(从虚地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间”。而较低的3G字节(从虚地址0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间”。
因为每个进程可以通过系统调用进入内核,因此,Linux内核空间由系统内的所有进程共享。
于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟地址空间(也叫虚拟内存).每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的。最高的1GB内核空间则为所有进程以及内核所共享。另外,进程的“用户空间”也叫“地址空间”,在后面的叙述中,我们对这两个术语不再区分。
用户空间不是进程共享的,而是进程隔离的。每个进程最大都可以有3GB的用户空间。一个进程对其中一个地址的访问,与其它进程对于同一地址的访问绝不冲突。
什么是内存?有何作用?
内存可存放数据。程序执行前需要先放到内存中才能被CPU处理——缓和CPU与硬盘之间的速度矛盾。
在多道程序环境下,系统中会有多个程序并发执行,也就 是说会有多个程序的数据需要同时放到内存中。那么会给内存的存储单元编地址。
内存地址从0 开始,每个 地址对应一 个存储单元。
如果计算机“按字节编址”, 则每个存储单元大小为 1字节,即 1B,即 8个二进制位。
如果字长为16位的计算机 “按字编址”,则每个存 储单元大小为 1个字;每个字的大小为 16 个二进制位。
指令的工作原理:
指令的工作基于“地址”。 每个地址对应一个数据的存储单元。
程序经过编译、链接 后生成的指令中指明 的是逻辑地址(相对地址),即:相对于进程的起始地址而言。 在逻辑空间中每条指令的地址和指令中要访问的操作数地址统称为逻辑地址 。很简单,逻辑地址就是你源程序里使用的地址,或者源代码经过编译以后编译器将一些标号,变量转换成的地址。
物理地址 :内存是由若干个存储单元组成的,每个存储单元有一个编号,这种编号可唯一标识一个存储单元(绝对地址)
虚拟地址 (virtual address): CPU启动保护模式后,程序运行在虚拟地址空间中。虚拟地址是Windows程序时运行在386保护模式下,这样程序访问存储器所使用的逻辑地址称为虚拟地注意,并不是所有的“程序”都是运行在虚拟地址中。CPU在启动的时候是运行在实模式的,Bootloader以及内核在初始化页表之前并不使用虚拟地址,而是直接使用物理地址的。
线性地址(Linear Address): 是逻辑地址到物理地址变换之间的中间层。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是线性地址。
目标程序与可执行程序:
目标程序:又称为“目的程序”,为源程序经编译可直接被计算机运行的机器码集合,在计算机文件上以.obj作扩展名,由语言处理程序(汇编程序,编译程序,解释程序)将源程序处理(汇编,编译,解释)成与之等价的由机器码构成的。
可执行程序:目标代码尽管已经是机器指令,但是还不能运行,因为目标程序还没有解决函数调用问题,需要将各个目标程序与库函数连接(链接),才能形成完整的可执行程序。
程序如何运行:
编译:由编译程序(Compiler)将用户源代码编译成cpu可执行的目标代码,产生了若干个目标模块(Object Module)(即若干程序段)。形成的目标代码,每个目标代码都是以0为基址顺序进行编址,原来用符号名访问的单元用具体的数据——单元号取代。这样生成的目标程序占据一定的地址空间,称为作业的逻辑地址空间,简称逻辑空间。
链接: 由链接程序(Linker)将编译后形成的一组目标模块(程序段),以及它们所需要的库函数链接在一起,形成一个完整的装入模块(Load Module)。
解决内存泄漏自动重启系统 篇3
A:你所说的这个问题通常被称为“内存泄漏”,也就是说Android应用关闭后系统依然不释放相应的内存。这样剩余的内存就会越来越少,最后导致后台进程频频重新启动。既然已经知道重新启动是最好的解决方法,那么就可以安装一个名为Phoenix的应用,这样就可以根据需要设置系统自动重启的条件,当条件符合以后就会自动重启。
◆ 重新找回支付宝的手势密码
Q:我最近将支付宝应用升级到最新版本,结果发现常用的手势密码没有了,取而代之的是系统的Touch ID功能。那么有没有什么方法,可以重新使用手势密码呢?
A:支付宝并没有完全取消手势密码,所以要想使用的话,首先打开支付宝,通过“服务窗”找到“支付宝客户中心”,接着点击左下角“遇到问题”中的“服务大厅”这项。然后在输入框里面输入“如何开启手势密码”,找到答案以后根据提示点击“设置手势密码”,最后即可设置对应的手势密码了。
◆ 利用空格键快速选择词组
Q:我最近买了一个iPhone 6的手机,用着感觉还不错,就是屏幕大了单手操作不方便,尤其是在文字输入的时候,选词非常麻烦。那么有没有什么方法可以解决这个问题?
A:其实要解决这个问题还是很简单的,通过键盘中的空格键就可以完成操作。比如要选择第一个词组就按一下空格键,这时光标就会自动移动到这个词组上,再点击“确认”按钮进行提交即可。如果要选择第二个词组,连续按两下空格键即可选择,其他的操作以此类推(前提是不能开启“句号快捷键”功能)。
◆ 通过手机扫描图片中的文本
Q:走到街上经常会看到一些推广资料,有的内容可能觉得以后会有些用,所以就会通过手机将其拍摄下来。那么有没有什么方法,可以将图片中的文字转换出来?
A:其实利用拥有OCR技术的软件,就可以解决你所遇到的问题。比如微软最新发布的“Office Lens”应用,通过它就可以轻松地识别出图片中的中文以及其他文字信息。识别完成以后会将其转换为Word文件,这样通过编辑器就可以进行编辑操作了。
◆ 微信朋友圈缓存图片的存放位置
Q:以前我曾经浏览过一个朋友圈好友的图片,但是今天发现好友把朋友圈那张图片删了。请问一下我手机里还缓存有这张图片吗?这张图片应该放在Android系统的哪个文件夹中?
金士顿系统指定内存 篇4
当年DIY红火的时候, 金士顿向来都是点名率很高的内存品牌, 经过这么多年的积累, 也把这种优势复制到了笔记本内存上。系统指定内存经过特殊设计, 各种延时设置针对特定品牌笔记本进行匹配。在选料上系统指定内存采用优质的组件, 并通过100%的测试与保证。同时, 系统指定内存的价格却要比原厂内存便宜得多, 尤其对于一些对兼容性和稳定性有较高要求的行业用户而言更具性价比。如今, 金士顿的系统指定内存共针对宏碁、苹果、华硕、戴尔、富士通、惠普、联想和东芝等品牌进行优化, 涵盖了目前主流的品牌。为了方便用户识别, 系统指定内存也有自己独特的命名规则——型号的前三位字母代表了具体优化的品牌。
金士顿会对每个新模组的模型执行一套严谨的测试流程, 确保模组设计的可靠性、统一性和兼容性, 以保证制造的每个模组都与使用模组的系统或系统类别100%兼容。每个新设计都要接受一系列审查和测试流程。同时, 金士顿一贯坚持对所有成品进行全面生产测试, 并采用不同类型的测试设备进行生产测试。设计和有效利用测试设备及软件方面的专业技术是使金士顿测试流程与众不同的关键因素之一。此外, 金士顿还聘请专业人员并采用必要资源以准确高效地执行测试程序, 并不断投资最新测试设备并改进个性化设计的测试硬件和软件。所有这些严格措施的执行都使得金士顿内存的质量数十年如一日, 早已成为行业不老的传奇。为了方便用户, 金士顿还强化了渠道体系, 推出了金士顿放心店, 仅有极少数有实力的代理商才能加入这一体系。同时, 各地完善的售后体系也保证了金士顿内存终生质保的实施。
内存系统 篇5
在Linux下操作频繁时,物理内存会被快速用完,当操作结束后,物理内存没有被正常的释放,而一直当作caching,影响系统的正常运行,今天就来谈谈如何能释放这一部分被占用的内存,
1、打开Linux命令窗口,可使用快捷键Ctrl+Alt+T打开
2、首先查看一下当前Linux系统内存使用情况,使用命令:Free –m,total 内存总数,used 已经使用的内存数,free 空闲的内存数
3、接下来的操作需要先获取高级用户权限,输入命令:sudo -i,确定后输入高级用户密码
4、先进行拷贝文件拷贝,增加内存使用量(即used的占用量),输入命令: cp -r /etc ~/test/
5、执行命令结束后,再次查看一下当前Linux系统内存使用情况,发现有70M的内存被cached用了,
使用命令:Free –m
6、接下来释放已被占用的缓存,输入命令: cat /proc/sys/vm/drop_caches,回车后返回结果0
7、输入命令:sync,回车后继续输入命令:echo 3 > /proc/sys/vm/drop_caches,回车后继续输入命令:cat /proc/sys/vm/drop_caches,回车后返回结果3,是将/proc/sys/vm/drop_caches值设为3
8、缓存释放已经完成了,再次执行命令Free –m看看,通过图中可以对比看到,内存被释放了218M。
内存系统 篇6
关键词:Windows操作系统;内存;优化管理
中图分类号:TP316.7文献标识码:B文章编号:1673-8454(2008)24-0060-02
一、引言
内存是计算机的数据存储设备之一,它与CPU、高速缓存器等共同决定计算机的运行速度。因此,如何优化内存的管理,提高内存的使用效率,是提高计算机运行速度的重要手段。下面就Windows操作系统,谈谈优化内存管理、提高内存的使用效率的八种方法。
二、提高内存使用效率的八种方法
1.改变页面文件的位置
改变页面文件的位置目的主要是为了保持虚拟内存的连续性。因为硬盘读取数据是靠磁头在磁性物质上读取,页面文件放在磁盘上的不同区域,磁头就要跳来跳去,自然不利于提高效率。而且系统盘文件众多,虚拟内存肯定不连续,因此要将其放到其他盘上。
改变页面文件位置的方法是:用鼠标右键点击“我的电脑”,选择“属性→高级→性能设置→高级→更改虚拟内存”,在驱动器栏里选择想要改变到的位置即可。值得注意的是,当移动好页面文件后,要将原来的文件删除(系统不会自动删除)。
2.改变页面文件的大小
改变了页面文件的位置后,我们还可以对它的大小进行一些调整。调整时需要注意,不要将最大、最小页面文件设为等值。因为通常内存不会真正“塞满”,它会在内存储量到达一定程度时,自动将一部分暂时不用的数据放到硬盘中。最小页面文件越大,所占比例就越低,执行的速度也就越慢。最大页面文件是极限值,有时打开很多程序,内存和最小页面文件都已“塞满”,就会自动溢出到最大页面文件。所以将两者设为等值是不合理的。一般情况下,最小页面文件设得小些,这样能在内存中尽可能存储更多数据,效率就越高。最大页面文件设得大些,以免出现“满员”的情况。
3.调整高速缓存区域的大小
可以在“计算机的主要用途”选项卡中设置系统利用高速缓存的比例。如果系统的内存较多,可选择“网络服务器”,这样系统将用较多的内存作为高速缓存。在CD-ROM标签中,可以直接调节系统用多少内存作为CD-ROM光盘读写的高速缓存。
4.监视内存
系统的内存不管有多大,总是会用完的。虽然有虚拟内存,但由于硬盘的读写速度无法与内存的速度相比,所以在使用内存时,就要时刻监视内存的使用情况。Windows操作系统中提供了一个系统监视器,可以监视内存的使用情况。一般如果只有60%的内存资源可用,这时就要注意调整内存了,不然就会严重影响电脑的运行速度和系统性能。
5.及时释放内存空间
如果发现系统的内存不多了,就要注意释放内存。所谓释放内存,就是将驻留在内存中的数据从内存中释放出来。释放内存最简单有效的方法,就是重新启动计算机。另外,就是关闭暂时不用的程序。还有要注意剪贴板中如果存储了图像资料,是要占用大量内存空间的。这时只要剪贴几个字,就可以把内存中剪贴板上原有的图片冲掉,从而将它所占用的大量的内存释放出来。 6.优化内存中的数据
在Windows操作系统中,驻留内存中的数据越多,就越要占用内存资源。所以,桌面上和任务栏中的快捷图标不要设置得太多。如果内存资源较为紧张,可以考虑尽量少用各种后台驻留的程序。平时在操作电脑时,不要打开太多的文件或窗口。长时间地使用计算机后,如果没有重新启动计算机,内存中的数据排列就有可能因为比较混乱,从而导致系统性能的下降。这时可以重新启动计算机。
7.扩大虚拟内存容量
如果计算机的硬盘够大,可以打开“控制面板”中的“系统”,在“性能”选项中打开“虚拟内存”,选择第二项,用户自己设定虚拟内存设置,指向一个较少用的硬盘,并把最大值和最小值都设定为一个固定值,大小为物理内存的2倍左右。这样,虚拟存储器在使用硬盘时,就不用迁就其忽大忽小的差别,而将固定的空间作为虚拟内存,加快存取速度。虚拟内存的设置最好在“磁盘碎片整理”之后进行,这样虚拟内存就分布在一个连续的、无碎片文件的空间上,可以更好地发挥作用。
8.提高系统其他部件的性能
计算机其他部件的性能对内存的使用也有较大的影响,如总线类型、CPU、硬盘和显存等。如果显存太小,而显示的数据量很大,再多的内存也是不可能提高其运行速度和系统效率的。如果硬盘的速度太慢,则会严重影响整个系统的工作。
三、结束语
当然, 优化内存管理,提高内存的使用效率的方法并不仅限于这八种,还有诸如优化BIOS的设置、整理优化注册表等等。只有根据计算机工作的具体状态,采取恰当的方式、方法,才能取得令人满意的优化效果。
参考文献:
[1]李笑梅,王新川.谈微机的优化内存管理[J].河北省科学院学报,2000(4).
[2]朱文鸣.加强Windows系统的内存管理[J].科学时代,2007(3).
内存数据库系统故障恢复技术研究 篇7
关键词:内存数据库,故障,恢复技术
内存数据库运行在内存环境中,更易受到软件错误、系统崩溃、系统掉电等因素影响,致使系统出现故障而不能继续运行。在内存数据库出现故障后,如何及时有效的恢复,使故障对数据库性能的影响降低到最小限度,显得至关重要。内存数据库的故障类型包括事务、系统和介质等三种,文章重点对系统故障进行探讨,给出相关内容及解决处理方法。
1系统故障的概念
系统故障是指在运行的过程中,由于某种事件迫使系统停止运转并经重新启动才能正常运转,掉电和软件错误就属于两类典型的系统故障。内存数据库主版本存储在内存中,掉电后内存中的内容全部消失,而常见的软件错误可能覆盖主存的一部分,它们都能使系统出现故障停止运行。系统故障发生后,有些已提交事务对数据库的更新还没有写入到外存数据库。 这时,作为恢复处理中最重要的一环,重装数据库以及重装过程中的恢复能将数据库有效地“还原”到某一种一致性状态。 完全可以来说,系统故障一旦发生,只需将外存数据库载入到内存,而后对undo起始点后的日志进行undo操作就可以将数据库恢复到离故障点最近的一致性状态。总的来说,系统故障恢复的关键点是重载外存数据库到内存中及利用日志工具恢复,那么如何有效的重载入外存数据库和快速高效的日志恢复便成为解决问题的重点。
2重载恢复
重载指系统出现故障之后,重新启动,在此过程中,恢复管理器根据日志和外存数据库的信息先将未超截止期的活动事务所需的数据装入内存,若没有超过重装阈值,则将等待事务所需的数据装入,直到重装阈值。内存数据库的故障恢复时, 在不(或尽量少)影响实时事务的定时限制满足的情况下,优先载入优先级最高的事务和下一个要访问的数据,紧接着将需要紧迫执行的事务启动,此过程中选择数据逐步载入到内存时要按照某种策略进行。内存数据库载入策略的好坏直接影响主动实时数据库系统的性能,一旦采取的策略不当,最先载入的数据将闲置一段时间,而紧迫要运行的事务的数据却未被载入内存中,这样一来这些无用和有用数据将频繁循环交换。这对时间有严格要求的实时事务来说,将是一种灾难。
2.1重载算法概述
并发重载算法较为典型的有频率装载(FR)、智能装载(SR)和顺序优先级装载(ORP ),其共同点是通过预测需要立即使用的页面,并依此降低重载时间。这三者的区别在于磁盘备份的结构、是否利用数据访问频率、重装优先级、重装粒度。所谓重载粒度就是数据重载的最小单元,在这个单元的数据载入过程中,不会发生抢占,除此之外高优先级装入可以抢占低优先级装入。这些算法区分等待事务和执行事务。等待事务就是那些在系统崩溃时还未提交的激活事务,而执行事务则是在系统重新开始工作后到达的事务。
2.2改进的重载算法
该算法充分考虑了上述各重载算法的优点,同时参考重载事务的预分析、数据载入的影响因素和数据交换在数据库运行时的策略,具体的实现算法如下。
第一步:建立恢复缓冲区和脏页表,给出等待事务的标号。
第二步:将系统信息重载到MMDB系统区。
第三步:标识故障时处于活动和等待状态的事务及其存储所需的数据库片,并将这些数据库片组合在一起。组合的原则是按照柱面的不同确定,同时充分参照磁盘数据库目录提供的信息。
第四步:将外存数据重载到MMDB主数据区,当数据量达到重装阀值(RT)停止重载。重载的优先级策略如下:
首先以存取频率由高到低的顺序作为基础,将“等待”事务按照其优先级由高到低的顺序载入其数据;
其次根据日志对离发生故障最近一次的检查点之后被修改的脏数据页进行数据恢复;
最后将其余数据载入,载入时依照存取频率的高低顺序进行。
第五步:复制己提交事务的“后映像”,将这些都复制到其私有的缓冲区。
第六步:重载到达阀值,接着启动系统运行并开始处理事务。
第七步:重载其他的外存数据到MMDB主数据区,重载的优先级策略如下:
首先按请求载入新到达的执行事务所需求的相应数据库片;
其次载入“等待”事务所需的其他数据库片,仍然以柱面为基础;
最后载入其他柱面数据,载入时依据磁盘数据库的存储顺序进行。
2.3改进算法的实验与结论
本实验重写Hsqldb的恢复模块,将上面提出的重载算法编程实现,并进行实验对比。对比时,按照分别插入不同数目的记录,分别是100、1000、10000、100000。在数据库运行过程中强制执行关闭操作,得到其相应的日志文件。Hsqldb的顺序重载和按优先级重载的结果如表1和图1所示:
从图1可以看出:刚开始数据优先级重载的优越性并不明显,当插入记录的条数达到1000条后,按优先级重载的良好性能才能体现出来。那么在高并发的适应应用环境下,按优先级的重载性能优于顺序重载。
结果表明:1)数据优先级算法时间开销少于顺序重载算法;2) 一个有效的重载算法对于内存数据库系统来说是非常重要的;3) 事务优先级和数据的各种特性在设计实时内存数据库重载算法时显得尤为关键。
2.4重载后的恢复策略
系统故障恢复由两个步骤组成,分别是重载和重载后的恢复。重载后的恢复是指根据日志和检查点执行的相应操作,恢复数据库到离系统崩溃时最近一次的一致性状态。在系统重启过程中一旦发现脏页,将根据磁盘上的日志和数据库进行重载恢复,具体步骤如下:
第一步:发现到最后一个检查点。
第二步:从检查点中读入以下内容到内存:1完整的数据库镜像;2稳定全局日志尾指针;3活动事务表,包括所有活动事务的TID和状态信息;4所有活动事务的undo日志;5系统最后分配的事务提交顺序号csn。
第三步:在稳定日志中,将当前稳定日志尾指针作为开头, 按照自后向前的顺序进行搜索,直至寻找到第一个提交/失败记录,并移动稳定日志尾指针到该点。
第四步:将读入的检查点中记录的稳定日志尾指针作为起点,按照由前向后的顺序遍历日志直至日志尾,并执行以下操作:
第五步:对于在检查点处于活动状态的事务,如果redo日志中没有提交记录<commit Ti,csn(Ti)>且其状态也未被标记为“提交中”,那么从检查点中找到相应的undo日志并执行相应操作。
3小结
内存数据库中间件系统设计方案 篇8
内存数据库是对计算机内存进行优化的处理,将数据常驻内存中实现全事务处理的数据库系统。目前在国内电信行业已经是普遍使用了,其中主要是TT、Altibase、EXtremeDB。本系统主要是利用Hibernate实现一个内存数据库和客户端的中间件,从而向程序员提供一个基Hibernate的统一接口,方便对HSqlDB进行访问。
1 Hibernate简介
Hibernate是一种新的ORM映射工具,它同时提供了从Java类到数据表的映射和数据查询、恢复等机制,实现数据层对象的持久性。相对于使用JDBC和SQL来手工操作数据库,使用Hibernate可以大大减少操作数据库的工作量,并且Hibernate可以和多种Web服务器以及应用服务器良好地集成。ORM即对象关系映射。它是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的操作转化为对这些对象的操作。
2 HSqldb简介
HSqldb是一个开放源代码的JAVA数据库,其具有标准的SQL语法和JAVA接口,它可以自由使用和分发,非常简洁和快速。具有Server模式、进程内模式(In-Process)和内存模式(MemoryOnly)三种。
3 内存数据库中间件系统结构及实现
3.1 系统的总体结构
系统在应用时的分层模型如图1。Application指用于应用程序,Hibernate是JAVA平台向程序员提供的统一的编程接口和平台,再往下一层的Hibernate Data Provider for HSqlDB就是本项目实现的核心部分,它调用下层的HSqlDB数据库接口,作为Hibernate平台中的一部分,向程序员提供针对HSqlDB数据库的操作。本系统中包含一个数据库表转移部件,用于将SQL Server中的数据转存到HSqlDB中,这就使得系统的移植更加方便。
3.2 Hibernate
Data-Provider for HSqlDB Hibernate DataProvider for HSqlDB逻辑上与Hibernate Data Provider for SQL Server等在同一层次。本系统为简化系统复杂度,减少层次以优化性能,直接提供一个面向HSqlDB的数据提供程序。
此数据提供程序使用JAVA语言实现,调用了hsqldb.jar提供的org.hsqldb.jdbcDriver驱动接口,将接口的相关信息包括用户名和密码写入到配置文件中。核心类部分包括Configure,SessionFactory,Session,扩展类部分包括HsqldbCommandBuilder、HsqldbParameter、HsqldbParameterCollection和HsqldbTransaction中的部分接口。数据提供程序最终以HsqldbDataProvider.jar包文件的形式供程序员调用。使用本数据提供程序,程序员可以通过统一的接口,像对SQL Server数据库一样,通过sql语句对HSqlDB数据库进行基本的查询、修改、插入、删除操作。
3.3 数据库表的迁移
数据库表的迁移是数据转换程序提供的数据转换功能,使原来存放在SQL Server数据库中的数据批量转存到HSqlDB数据库中的相同表中,以方便系统的移植。
数据库表的迁移的工作原理是:(1)首先利用Hibernate Data Provider for SQL Server,将SQL Server数据库中的数据提取出来,并转存为XML格式。(2)将生成的XML文件进行格式转换为HSqlDB数据库可以识别的XML文件。(3)把转换好的XML文件导入HSqlDB数据库。经过上述三步,数据转换程序就完成了数据的转移。目前本系统中的数据转换器只能提供单个表中数据的批量转换。要将整个数据库进行移植,需要手工将每个表依次进行转换。
4 性能测试与结论
本系统使用一个简易的JSP网站进行了基本测试工作,在JAVA平台上,利用Hibernate Data Provider for HSqlDB和Hibernate Data Provider for SQL Server,分别对HSqlDB和SQL Server数据库进行了对比测试。
测试中使用的数据库表格式为:persons(name int,age int,address string)。
4.1 查询测试
进行查询操作的测试是,HSqlDB数据库和SQL Server数据库中分别存放好300000条数据。从300000条数据中查询2000条数据的时间:HSqlDB需6.263秒、SQL Server需12.324秒。
4.2 插入测试
分别插入30000条记录时,HSqlDB和SQL Server用时分别为:31.528秒和52.143秒。当插入数据量较少时,HSqlDB的性能并不比SQL Server高。主要是因为SQL Server和Hibernate都有缓存机制,当数据量小时,其缓存可以存放所有数据,因此HSqlDB无法体现其优势。
5 结论
在操作的数据量足够大时(大于磁盘数据库系统的数据缓存),内存数据库HSqlDB与传统的磁盘数据库相比,性能有明显的提升。尤其是在进行只读操作时,性能提升更加明显,通常可以将时间缩短1到2个数量级。数据量较小的情况下,内存数据库的性能提升并不明显。
测试结果显示,内存数据HSqlDB较适合存在大量只读操作的系统,如经典文献储藏网站、各类信息消息的发布查询网站等。
摘要:内存数据库IMDB通过JAVA作为操作数据语言实现的程序可以为数据库事务逻辑处理带来的性能提升。该系统利用当前流行的SSH框架中的Hibernate实现Date Provider for HSqlDB,程序员可以通过相应的接口对HSqlDB进行查询、添加、删除、更新等操作,并在大容量的数据操作时,效果会有明显的提升。
关键词:HSqlDB,JAVA,Hibernate,内存数据库系统
参考文献
内存系统 篇9
关键词:仿真系统,体系结构,共享内存,进程间通信
0引言
随着分布交互式仿真技术的不断发展, 利用VC等软件平台, 结合成熟的仿真引擎开发武器装备仿真系统逐渐成为军事训练、试验领域研究的热点。但是鉴于军事仿真中武器装备结构复杂、功能繁多等特点, 基于目前通行体系结构的仿真系统在实际的使用中逐渐暴露出了系统开发、维护困难, 可拓展性差等问题。
本文在结合武器系统的特点, 分析现有仿真系统的缺点的基础上, 提出基于共享内存的武器装备仿真系统的体系结构。为了更直观地阐述系统的结构和开发过程, 本文将以坦克分队模拟训练中的炮长节点为例进行说明。
1现有仿真系统的缺点
军事仿真具有视景逼真、交互性强、仿真节点多的特点, 现有的仿真系统通常是利用VC等开发平台实现网络通信、人机交互和三维图形显示等功能。
此种结构的仿真系统主要几个方面的问题:①对系统开发人员要求过高;②系统的可读性和可维护性差;③通用性较差。为了解决上述问题, 本文提出基于共享内存机制的装备仿真系统结构。将仿真系统的三维视景显示和数学解算模型、网络通信等相互分离形成独立的进程, 利用共享内存完成数据的交换和同步, 组成仿真系统。
2基于共享内存的仿真系统体系结构
2.1共享内存的介绍共享内存指在计算机中将同一块物理内存映射到两个或者多个进程各自的进程地址空间, 各进程可以及时获取其他进程对共享内存中数据的更新[1]。
在分布交互式仿真中, 使用共享内存技术, 具有如下优点[2]:
①系统的开发不再仅仅局限于仿真引擎中, 系统模块化程度更高, 方便管理和改进, 增强通用性和开发效率;
②可以选择性地获取仿真过程中的各种数据, 方便其他进程使用和分析仿真结果;
③系统开销小, 有利于硬件资源的高效应用;
④通信效率较高, 可以满足仿真中数据交换高频率、实时性要求。
2.2仿真系统的结构为了解决现有仿真系统所存在的问题, 我们对仿真系统的结构进行了重新定义, 将仿真系统按照功能进行模块化划分:在分布式仿真HLA/RTI结构的基础上, 使用RV引擎进行三维视景的模拟, 利用Simulink等数学分析工具对仿真系统的各项数学模型进行建模, 炮长终端等装备部件采用C++独立建模, 各个模块相互独立运行, 在基于共享内存的通信协议下实现仿真的同步和数据的交换。网络通信模块从共享内存中将本机各项仿真数据整合为联邦盟员与网络其他节点进行通信。如图1所示。
在炮长节点的仿真计算机中, 各个模块的任务和功能大致如表1所示。
3基于共享内存的进程间通信机制
基于共享内存的仿真系统体系结构中, 共享内存作为数据存储和交换的公共逻辑内存, 是连接各个模块组成仿真系统的纽带, 所以各模块仿真进程间基于共享内存的通信协议是系统实现的关键。
3.1共享内存的建立两个仿真进程之间共享虚拟内存大致步骤为[3]:①在一个应用程序中利用Create File Mapping () 函数创建一段有名称标示的内存空间, 并设置其大小和访问权限;②调用Map View Of File () 函数将该内存映射到本程序的地址空间中;③另一个应用程序可以直接或者通过通讯管理程序利用Open File Mapping () 函数访问该内存对象, 一旦访问成功获得其句柄, 则该应用程序也将把该空间映射到自身地址空间中, 这个内存空间就可以被当作共享内存来使用。
本文将共享内存进行分块, 根据数据写入方的不同创建不同的结构体, 并将共享内存自动返回的空类型LPVOID句柄转化为变量结构体指针, 利用该指针加上偏移量就可以访问到具体变量对应的空间完成读写。
3.2共享内存的访问控制由于多个进程共享一段内存, 为了实现其访问逻辑, 本文采取信号量的方式来协调进程对共享内存中数据的读写操作。
如图3所示, 为实现装甲车辆火控系统解算射击提前量和方位角, 需要三维视景仿真程序和火控系统数学模型进行通信。在RV引擎中获取激光测距、火炮运动角速度、坦克倾斜角等数据, 写入共享内存而后发出信号量1;数学模型检测到信号量1后利用这些数据解算得出射击提前量和方位角并发送信号量2;视景引擎又根据解算的提前量和方位角驱动火炮运动。通过此访问控制机制, 保证了数据传输的逻辑顺序。
4应用实例
装甲装备模拟训练中炮长节点的装甲装备模型结构在1.2中已经予以讨论, 下面就各部分的具体的建模方法和其对共享内存的读写内容及读写方法分别做以介绍。
4.1三维视景模型本文采用RV引擎建立视景模型。结合1.2中视景模型的任务, 可以分析出在坦克射击训练过程中, 视景模型的输出数据主要有:坦克坐标、坦克运动速度和方向等。这些数据都可以通过简单的编程获取。RV引擎获取的数据经过转换, 转变为标准的C++数据类型写入到共享内存中结构体的相应位置。如下是射击时, 结构体中用于解算射击诸元所需的部分变量, 数学模型获取这些数据进行瞄准角和提前量的解算。
4.2数学模型火控计算机最主要的功能之一就是利用其EPROM中由各种弹药的射表所逼近的弹道函数完成瞄准叫和方位修正量的计算。在实装中通常需要求出瞄准角、飞行时间、横风、药温、气温和初速减退量等与距离的函数关系。为了简便起见, 我们只对对射击影响最大的瞄准角和飞行时间进行模拟。
一般情况下, 弹道函数中瞄准角的计算公式为:
其中D为目标距离, a1、a2、a3为弹道系数。如下是共享内存中数学模型写入的结构体中稳像工况相关的部分内容。
4.3炮长终端仿真进程在射击训练中炮长终端主要是负责部分信号量的发送和当前火炮武器系统状态的显示。
炮长终端对共享内存的写入数据, 大多是工况选择、弹种选择等信号量, 提供给其他模块。如下是其写入共享内存的结构体内容。
4.4网络通信进程就整个模拟训练系统而言, 目前多采用HLA/RTI的结构。HLA提供通用的技术框架和开发规范, 而运行支撑平台RTI是HLA接口规范的具体实现, 目的在于将仿真应用、运行管理和底层通信等基本功能的分离, 实现盟员间数据的有序和按需传送。文献[4]详细介绍了基于分布式共享内存的RTI通信机制[4], 在此不再赘述。
5结束语
图3为炮长节点使用破甲弹对1180m外目标进行射击的效果, 各项数据采集、传输正常, 弹道显示正确, 能够较为准确地模拟坦克射击的过程。
测试运行结果表明, 基于共享内存的装备模型建模可以满足分布式交互仿真的实时性要求, 提高了模型的开发效率和可维护性。此种仿真系统结构在军事模拟训练、试验领域有较好的应用前景。
参考文献
[1]刘畅.分部交互仿真若干问题的研究[D].北京:北京邮电大学, 2008.
[2]梁强, 鲁鹤松, 杜君, 等.仿真软件多进程间数据交互实现研究[J].系统仿真学报, 2013, 25 (S) :137-141.
[3]赵晓冬, 康凤举, 陈法扬.舰艇编队作战视景仿真系统研究[J].火力与指挥控制, 2011, 36 (2) :93-96.
内存系统 篇10
日志是利用某种方式记录系统产生的文本信息,包括系统运行记录、程序调试信息、安全审计信息等,对于软件系统的开发、调试与安全都非常重要。系统开发时,日志信息可为系统排错、性能优化提供有力的帮助;系统发布后,日志还将记录系统每天产生的大量信息,为系统的安全监测和运行维护提供数据[1,2]。传统的日志记录代码内嵌在业务处理进程内,日志记录与业务处理串行,日志输出势必影响业务处理速度,若日志信息过于庞大,甚至会阻塞正常的业务处理;另外,若系统内不同子系统各自记录日志,必然存在日志的格式、语义不一致,并且它们分散在各处,缺乏访问控制及完整性保护,存在着效率低、重用性差、维护成本高、规范不一致等诸多缺点[2]。合理的日志管理系统应具备以下特点:1)独立性:日志系统不能作为项目的一个模块,应独立运行,当日志系统开启时记录日志,关闭时不记录;2)低耦合性:日志系统不能和项目紧密耦合,日志系统只对外提供日志记录接口,当系统要输出日志时,只需简单地调用接口即可;3)日志多样性:日志系统应提供多种类型的日志,为项目的调试、信息输出、错误记录和安全审计提供支持;4)重用性:日志系统可在无需修改或者少量修改的情况下应用于新的项目中;5)延迟输出:日志处理应在不影响业务处理的情况下完成。根据分析和研究,本文为实现上述特性的通用日志系统提供了一种设计方案。
1 共享内存与进程通信
为了提高计算机系统的效率,增强计算机系统内各种硬件的并行操作能力,所有基于多道程序设计的操作系统都建立在进程的概念之上。然而为了避免不同的进程之间产生干扰,即使是父子进程,都具有各自不同的进程内存空间,因此,进程之间的信息传递不可能通过变量或其它数据结构直接进行,而只能通过进程间通信来完成[3,4]。进程通信是实现多进程协作与同步的常用工具,常见的进程通信方式有:文件、命名管道、消息队列、共享内存、信号量、命名互斥和命名事件等[3,5,6]。其中,共享内存是一种最有效的进程间通信方式,也是最快的IPC形式[7,8]。两个不同进程A、B共享内存的含义是,同一块物理内存被映射到进程A、B各自的进程地址空间,如图1所示。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。值得注意的是,图1所示的进程A、B并没有分别重新开辟一个大小相同的内存空间,它们只是做了共享内存地址映射,不同进程对各自的这部分空间操作,将间接地操作同一块内存。由于多个进程共享同一块内存区域,必然需要进程同步机制[9],本系统采用命名互斥实现共享内存的互斥访问、利用命名事件实现多进程的协同操作。
1.1 共享内存的创建
共享内存可分为文件共享内存和独立共享内存。建立文件共享内存需要先打开磁盘上的文件,然后利用该文件句柄(HANDLE)创建一个指定大小(可与文件大小不同)的共享内存,然后载入文件数据到共享内存,之后对该共享内存的操作将会实时地更新到文件中,但无法追加数据到文件;独立共享内存是直接在物理内存中开辟的一块空间,对该共享内存的操作在没有输出到外部文件情况下,若系统退出,则共享内存中的数据将会丢失。
在Windows平台下,使用CreateFileMapping函数创建一个新的文件映射内核对象,参数hFile为文件句柄,当hFile为-1时,创建一个独立共享内存;参数dwMaximumSizeHigh和dwMaximumSizeLow是用于指定共享内存大小的高低32位,都为0时,则表示共享内存的大小与文件大小相同,如果创建的是独立共享内存,则不能都取0;参数lpName为共享内存名称,该名称是其它进程进行共享内存映射的依据,该名称必须唯一,不能与其他全局对象名称等相同,否则将导致创建失败。
1.2 共享内存的映像
创建共享内存之后,若要访问共享内存,应先使用OpenFileMapping方法打开共享内存映像,其参数lpName表示要打开的共享内存名称,该方法返回共享内存对象句柄,然后使用MapViewOfFile方法将共享内存对象映射到当前进程的地址空间,其参数hFileMappingObject为OpenFileMapping方法返回的共享内存对象句柄,该函数将返回内存映射的开始地址,之后就可以利用该地址对共享内存进行操作。
1.3 进程同步与协作
多进程操作同一个资源时必须保证读写一致性[8],确保共享内存访问一致性的最理想方式是原子操作[10],也称为线性化操作[11],在基于消息机制的系统下实现同步机制有:信号量、互斥对象、事件通知等[3]。本系统采用全局命名互斥对象,保证在同一时刻只有一个进程操作日志队列。在Windows平台下,某进程使用CreateMutex函数创建命名互斥内核对象,其它进程在操作共享内存时,需使用OpenMutex函数打开指定名称的互斥对象,然后利用WaitForSingleObject函数来获得互斥对象,取得互斥对象后就可以直接操作共享内存,操作完毕后可使用ReleaseMutex函数释放互斥对象。如果某个进程取得了该命名互斥对象,其他进程必须等待它释放才能获得该互斥对象的拥有权,从而保证了资源的互斥访问。
另一方面,为了实现多进程协同操作,本系统采用了命名通知事件,该事件由日志系统启动时利用CreateEvent函数创建。使用日志系统的其他进程(以下统称业务处理进程)在共享内存中植入日志后,通过OpenEvent函数获得该命名事件句柄,然后利用该句柄通过SetEvent函数通知日志系统对日志消息进行处理;日志系统处理完日志消息后,利用ResetEvent函数清除事件信号,以等待业务处理进程再次通知它处理消息,实现了多进程的协同操作。在本日志系统中,进程同步与协作均封装在日志系统对外提供的静态链接库中,业务处理进程只需简单地调用静态函数库中的接口即可完成工作,无需关心具体的实现细节。
2 松耦合日志系统设计
不同程序之间要相互交换数据,程序之间必然存在某种程度的关联,即耦合度。耦合度越小,程序独立性就越强,程序复杂度就越低,程序可维护性就越好。
2.1 日志系统结构设计
为了最大限度地降低日志系统与业务处理系统的耦合度,本系统采用了共享内存和事件通知相结合的架构。日志系统由一个主程序和一个静态函数库(API库)组成,主程序完成对日志管理的所有操作,API库为业务处理系统提供使用该日志系统的外部接口,其系统结构如图2所示,其中实线框为日志系统。
图2中的共享内存是本系统的日志输出缓冲区,缓冲输出减少了外部IO操作次数、可从根本上提高日志输出性能。为了降低系统复杂度和实现的难度,本系统设计了4个日志缓冲队列,分别保存4种不同的日志消息,由日志主线程启动时创建;同时设计了4个日志管理线程,分别对每个队列进行管理,负责把每个队列的信息分别输出到不同的外部文件中;由于日志的信息量巨大,若将所有日志信息输出到同一个文本文件,将不利于后期对日志的查看与分析,必须对日志信息进行归档。本系统约定,当日志文件LogTypeLog.dat中的日志条数超过25000时,就把当前的日志文件归档为LogTypeLog01.dat,而把原来的LogTypeLog01.dat归档为LogTypeLog02.dat,以此类推,最多保存99个归档文件,LogTypeLog.dat清空后继续保存最新的日志。其中LogType表示日志类型,名称根据日志类型的不同而不同。
2.2 日志队列结构设计
本日志系统设计了结构一致的4个循环队列,分别用于暂存系统输出信息、调试信息、错误信息和安全审计信息,其结构如图3所示。日志队列由1个头元素和1024个消息记录组成,头元素的wp字段值指示了当前可存放的消息记录下标,rp字段值指示了当前可读的消息记录下标,wp、rp初值为0,每个消息记录是一个长度为280的字符数组。其中缓冲队列长度由式(1)-式(3)估算:
式(1)中,P表示使用缓冲队列后性能提升百分比,M表示每10秒(系统每隔10秒清空一次队列,参看2.3.2节)内日志输出条数,L表示日志队列长度,HT表示硬盘IO周期,而MT表示内存存取周期,280为每条日志的最大字节数,4为32位机一次内存存取字节数,C为硬盘的读写缓存区容量。
因当前主流的SATA硬盘缓存至少32MB,硬盘的IO周期约为内存存取周期的三个数量级,并控制日志队列满时在一个磁盘IO周期完成输出,故取式(2):
把式(2)代入式(1)并简化后得式(3):
从式(3)看出,当队列到达一定长度后,再增加长度已经效果不大,为了方便计算机处理,本日志系统取日志长度为1024。队列结的构体如类型TMsgQue所示。
由于是循环队列,约定当wp等于rp时表示队列空,当(wp+1)%1024等于rp时表示队列满,故队列中最多可以暂存1023个消息记录[3],如图3所示。
2.3 日志系统算法设计
本日志系统由1个日志系统主线程、4个日志管理线程和1个静态链接库组成,如图2所示。
2.3.1 日志主线程算法
当日志系统启动时,日志主线程首先创建4个共享日志队列,接着为每个日志队列创建访问互斥对象和通知处理事件,通知事件初始为非信号状态,互斥对象初始为非占有状态;接着为每个日志队列创建一个管理线程,初始化日志输出所采取惰性处理策略[12],以避免日志处理进程阻塞业务处理进程,提高系统的整体性能。最后主线程进入无限等待,等待用户发出退出命令。主线程接收到退出命令后,向每个日志管理线程发出处理结束通知,待所有日志管理线程处理完毕并退出后,结束主线程,退出日志系统。
2.3.2 日志管理线程算法
日志管理线程被日志主线程创建启动后,首先清空自己所辖的日志队列,然后进入一个无限循环。在循环中首先判断主线程是否发出结束通知,若是,则把日志队列中的剩余数据输出到日志文件中,然后跳出循环,结束线程运行;否则,检查日志处理事件是否有信号,若有信号,先置日志处理事件为非信号状态,接着在获得共享内存访问互斥对象的情况下,检查日志队列是否已满,若队列已满,按内存块拷贝方式迅速拷贝整个日志队列到私有内存空间,同时清空共享内存中的日志队列并立即释放互斥对象,以避免日志处理系统长时间占有互斥对象而阻塞业务处理系统及时投递日志,最后在惰性策略下把私有内存中的日志输出到日志文件中;若队列不满,则置日志处理事件为非信号状态后返回;若日志处理事件无信号,则直接进入下一个循环处理。值得一提的是,此处不能设计成无限等待日志处理事件,否则线程无法及时响应日志系统退出事件,导致日志系统无法正常退出,而且日志管理线程必须每隔一段时间(比如10秒)检查一下队列是否有数据,若有数据,不管队列是否已满,都要输出日志,保证及时处理长时间缓冲区未满时的日志。
2.3.3 日志访问接口算法
需要日志输出的业务处理系统(如图2中的A、B、C系统),只需调用静态链接库中的相应接口,并提交所需登记的日志信息。接口函数首先查看共享内存访问互斥是否存在,若不存在(表示日志系统未运行),则函数直接返回,若存在,则先获得互斥对象,然后将日志植入日志队列,接着释放互斥对象,最后发出日志处理的事件通知;日志管理线程收到通知后把日志输出到外部文件,实现了日志的实时记录。该算法的设计,使得日志系统可以独立运行而不影响业处理程序的正常操作。
为方便外部程序输出各种形式的日志信息,本系统借鉴了C语言中标准输出函数printf的定义,采用动态参数的方法,支持各种类型变量的输出。在此,只以信息输出接口为例进行说明,因其它接口定义类似,不再一一细述。该接口定义如函数slogprintf所示,限于篇幅,定义中只给出部分重要代码。
从上看出,业务处理系统调用该接口与调用标准输出函数printf的语法一致。
3 耦合度与性能分析
耦合度是考量一个系统设计是否合理的一个重要指标,可从动态运行与静态开发两方面进行分析。动态上:从2.3.3节可知,当日志系统处于运行状态,日志访问接口可把日志植入日志队列,并由日志系统输出到外部文件中,而当日志系统未开启时,则日志访问接口直接返回,可见,动态上业务处理系统与本日志系统互不依赖,耦合度为零;静态上日志系统与其它业务处理系统存在编译依赖,可通过为多种语言提供相应的静态链接库来满足多种开发环境的需要。
在性能方面,首先,采用日志缓冲队列输出,减少了外部文件的IO操作,从根本上提升了系统性能;其次,业务处理系统在日志输出时采用投递式输出,调用日志接口后立即返回,几乎不影响业务处理进程的执行;最后,由于日志管理系统与其它系统分属于不同的进程,可最大限度地发挥多进程并行的优点,在多处理器环境下效果更佳。表1展示了某业务处理系统在不同平台下使用本日志系统和传统日志输出(日志输出代码分散在业务系统的逻辑代码中)两种日志记录方式的耗时对比。图4的耗时折线图更加直观地显示了日志性能比较,从图4可以看出,传统日志记录方式的时间代价与日志条数几乎成正比,而且当日志记录过多时会引发业务处理延时,对于实时性较高的系统是不允许的;使用本日志系统可以解决这些问题,而且在配置较低的平台下也能得到很好的性能。
4 结语
日志记录对于系统的开发与运行维护都具有重要意义,本文针对以往缺乏独立日志统一管理、日志输出性能低下、代码重用性差的缺点,提出了一种松耦合、运行独立、性能优越的日志管理系统设计方案,并提供了与C语言标准输出函数一致的日志访问接口,使用简单方便。该系统针对性强,运行稳定,已经应用在多个大型项目中,在实际的使用过程中,该系统有着非常良好的表现,极大地提高了系统的日志记录效率,值得在各项目中大力推广。另外,使用本系统还可以改善同机多系统日志管理混乱的问题。
参考文献
[1]胡孟梁,耿良,蔡瑞英.一种通用综合日志系统的设计与实现[J].计算机应用与软件,2008,25(5).
[2]王子靖,钱纯.对日志统一管理的安全审计系统的实现[J].计算机应用与软件,2012,29(3).
[3]Andrew S Tanenbaum.Operating Systems Design and Implementation [M].3rd ed.Prentice Hall,2006.
[4]孙文庆,刘秉权,肖镜辉.基于内存映射文件的数据共享技术研究与应用[J].微计算机应用,2005(2).
[5]胡小龙,江海花.Windows操作系统进程通信机制[J].计算机应用研究,2002(12).
[6]谢安明,邵美珍,郭志刚.Win32中多进程间的内存共享数据通信方法[J].无线电工程,2000(11).
[7]Larry Hughes,Hosein Marzi,Lin Yanting.A New Approach in Designing Interprocess Communication for Real-Time Systems[J].International Journal of Software Engineering and Knowledge Engineering, 2005,15(2).
[8]Phil Miller,Aaron Becker,Laxmikant Kale.Using shared arrays in message -driven parallel programs[J].Parallel Computing,2012,38(1 _ 2):66-74.
[9]Cheng Shao,Jennifer L Welch,Evelyn Pierce,et al.Multiwriter Consistency Conditions for Shared Memory Registers[J].SIAM J.on Computing, 2011(1).
[10]Lamport L.On interprocessor communication,PartsⅠandⅡ[J].Distrib. Comput,1986(1):77-101.
[11]Herlihy M,Wing J.Linearizability:A correctness condition for concurrent objects[J].ACM Trans.Programming Languages and Systems, 1990(12):463-492.
全新架构的内存 篇11
现在的内存在多内核处理器出现后开始成了系统的瓶颈,当前的内存模块由于带宽不高以及读写速度太慢,所以根本无法以足够快的速度将数据传输到处理器。当新一代的处理器出现时,这一问题将进一步恶化,因为新的处理器必然对内存的效率与性能提出更高的要求。与此同时,智能手机和平板电脑的快速发展也将对内存模块的能耗与体积有更高的要求,这些设备都需要内存在容量更大的同时体积更小并且更节能。为此,英特尔与镁光公司开发出了一个全新架构的内存模块:混合存储立方体(Hybrid Memory Cube,简称HMC),混合存储立方体上方是使用IBM硅通孔(Through Silicon Via,简称TSV,一种连接集成电路三维模块中各堆叠芯片的新技术)技术连接的芯片垂直堆栈,核心是垂直堆栈下方的一个小型的高速逻辑层,它能够快速、高效地为处理器的每一个内核传输数据。
速度快、能耗低
在2011年的英特尔IDF上,英特尔与镁光公司首次展示了包含4个内存层的混合存储立方体原型。在主板能够提供相应支持的情况下,它能以128GB/s的速度传输数据。当然,这对于主板厂商来说无疑是一个艰巨的任务,他们必须制造出能够处理如此庞大数据流的主板,如何才能够让混合存储立方体高达128GB/s的数据传输带宽不因主板而受影响将是一个不小的技术难题。与此同时,系统中硬盘等其他的设备,读写数据的速度也需要相应地提高,这可能必须寄希望于下一代的存储技术,新的技术使硬盘的速度达到目前固态硬盘的5倍。
与当前DRAM模块中缓慢的并行接口不同,混合存储立方体在硅通孔技术的支持下,芯片垂直堆栈与逻辑层之间的带宽高达1TB/s,相比目前最新的DDR3内存11GB/s的传输速度,创新的接口可以确保每个混合存储立方体的性能都在DDR3模块的15倍以上。除了需要频繁读写内存的Windows系统能够从中获益以外,视频编辑软件等密集型计算的应用也都将从中受益。
除此之外,混合存储立方体的逻辑层还解决了另一个问题。众所周知,现在多核芯处理器已经拥有多达16个内核,并且增加的趋势还很明显,而目前的内存模块必须通过外部内存控制器这一唯一的路径与处理器连接,因而无法为处理器的各个内核及时提供数据。混合存储立方体则不同,逻辑层矩阵开关能够从特定的存储层向某个处理器的内核定向发送数据,或者发送到其他连接在一起的混合存储立方体。处理器的每一个内核都能够与内存模块建立直接的连接,并且每一个连接都能够以最高的速度运行。因而,混合存储立方体不会在处理器内核数量持续增多的情况下成为瓶颈,即使处理器已经发展到近百个内核,混合存储立方体只需通过逻辑层提供更多的连接,即可保持内存与处理器之间的数据传输速度不受任何影响。
三星推出的RDIMM(Registered Dual In-line Memory Module,主流的DRAM模块解决方案)内存模块也采用类似的设计,同样使用IBM的硅通孔技术连接模块中的存储层,但是它缺少了一个类似混合存储立方体的逻辑层,仍然需要像普通的内存一样,通过外部内存控制器这一唯一的路径与处理器连接。因此,它对于多内核处理器的支持以及性能都无法与混合存储立方体相提并论。当然,与普通的DDR3内存模块相比,三星RDIMM内存模块仍然具有明显的优势,其存储密度提升了1倍,能耗也降低了40%。不过,得益于逻辑层的智能内存管理技术,混合存储立方体的优势则更为明显,传输每比特数据的能耗比三星RDIMM内存模块低30%。理论上,混合存储立方体比任何最新的DDR3模块传输每比特数据的能耗量要低70%。唯一的问题是,目前仍不清楚模块发热的情况如何,在内部数据高速传输的情况下,内存芯片产生的高温不可小觑,冷却内存堆栈有可能需要消耗额外的能源。
不局限于电脑的内存
混合存储立方体层叠式的架构使其拥有一个非常紧凑的结构,在主板上占用的空间比现有的RDIMM还要少近90%。因而,混合存储立方体可以广泛地应用于包括个人电脑在内的各种设备,甚至包括电视机、收音机和闹钟等。
据估计,2012年混合存储立方体将开始用于工作站和服务器,2013年将开始大量生产,2015年、2016年左右进入消费领域,也就是说,个人电脑用户可能需要到2015年才能用上混合存储立方体。
内存系统 篇12
数据库自诞生以来经过几十年时间的发展,已经走向成熟;另一方面,纯机械化也已不能满足许多行业生产和发展的需要;于是业务系统和当代数据库理所当然地走到了一起,向着自动化迈进。数据库的加入带来最直接的好处就是可以使大量的业务数据得以完好地保存,并且统一进行读写和业务调度,而目前看来,第三代关系型数据库做得最完善,其自身的优点结合突飞猛进的计算机硬件,使得关系数据库的应用范围越来越广,许多大数据量的实时性行业,如证券期货交易系统、电子商务、卫星导航等也包含在其中。
下面以一个典型的例子——证券交易清算系统为例简单介绍一下数据库的运作情况,该系统为证券公司提供开销户、行情转换、委托交易、清算对账等一系列功能。客户在某一营业部下委托时,系统将生成一笔委托单,发送给报盘系统,同时存储在数据库中。证券公司通过交易所给定的方式接收清算有关的dbf数据库文件,交易系统就通过清算数据接收,把dbf文件接收到数据库的一级清算表中,同时将保存在数据库中的公司当交易的二级数据进行合计,然后进行一二级对账,同时把返回的资金从客户的账户中进行加减。
然而,纯关系数据库在处理某些数据事务和业务流程上确实遇到了困难。主要反映在交易数据量大的时候会来不及下单并且会阻塞掉。有两次严重时几乎出现了不能正常交易的大事故。在求证过程中,我们查阅了不少资料,同时也发现了这类问题在几乎所有上规模的同类业务系统中都存在。
那么如何解决实时大数据量和现有关系数据库系统的矛盾呢?大家知道在内存中处理数据比在硬盘上面快得多,如果把数据库中经常用到和更新的表放到内存中去,事务运行时从内存而不是从硬盘里面读写数据,这样就会大大提高处理效率。鉴于以上思路,我们设计了一套完全适合该系统的内存机制来解决以上出现的问题。
2 内存机制的设计和实现
2.1 内存机制的前期设计
设计程序运行的主体,界面,内存表装载运行等,还要把客户的需求结合进来研究一些可实际运行的方案。目的是建立一个可以参考的原型化系统。主要包括以下几个方面:
1)界面操作参数设计,
2)进程和互斥管理,
3)内存机制的配置方法,
4)字段数据类型的支持和重建,
5)内存机制的运行和维护,
6)内存机制初始化,
7)内存表加载进程,
8)内存状态监控。
2.2 内存表设计
这是内存机制的核心内容。主要实现内存表储存、建立、控制、查询、修改等内容,为实施提供了导引和基准。
2.2.1 内存表的存储
和普通文件类似,内存表有表头、索引体和记录体3部分构成。表头部分存储该表的一些基本信息,索引体储存红黑索引树结点,记录体存放硬盘表中的数据镜像。表头的定义尤为重要,它需要存储的信息至少要有表ID、记录行所占字符数和最大行数,所处的物理位置等静态信息,此外还需要一些诸如当前记录数、起始空闲位置等动态信息等。表头的定义如下:
定义中包含表ID属性。它是一个内存首地址,对应唯一一张内存表。机制中的所有函数都是通过它来识别具体是哪张内存表。
2.2.2 表级操作
1) 内存表创建
创建内存表包括创建表头信息和分配内存空间两个方面。系统至少必须指定未来可能创建索引的数量、记录数、每条记录长度3项才能获得一个静态的分配值。
2) 打开内存表函数
如果文件被成功打开,此函数就返回一个共享表的句柄;失败时会返回NULL值,并输出具体的出错信息。
3) 获取内存表信息
该函数的功能为获取打开的共享内存表概要信息,以便操作者了解此表的对应关系、现今状态,还可以手工判断其是否需要进行维护和扩充。内存表的摘要信息存放在文件头中,返回的时候只要把这些信息全部输出就可以了。如果找不到句柄,就返回失败和错误信息。
4) 关闭内存表函数
该函数的功能为关闭打开内存表时返回的句柄SMTHandle。需要注意的是,关闭内存表不是删除内存表,其实际占用的内存空间不会被去除和释放。
5) 内存表清空
该函数的功能为快速删除整张表格的数据,相当于truncate命令。执行这句语句后,记录体被清空,但是表头和索引体仍然保留。
6) 内存表去除
当硬盘表被drop或发现建立的内存表不符合要求时,就要将其从系统内存中去除。
2.2.3 内存表查询
查询部分提供了基本功能包括:读取指定行记录、读取符合条件的记录、返回内存表基本信息(如记录数、索引数)等。这些操作也由上一级函数调用,不经过硬盘直接读取相应共享表的内存区块。在作查询操作时可以加共享锁,也可以不加锁。
2.2.4 内存表修改
当硬盘表进行修改操作后,为了业务功能函数能够取到正确值,内存表也必须同步修改。其方法和硬盘表相似,主要分为插入、更新、删除3种。
2.2.5 批量数据处理[2]
一个好的内存表需要提供便捷的批量处理能力,我们知道硬盘表一般是通过游标来处理的,频繁打开关闭游标等一系列操作会大大降低系统的运行效率。这也是整体效率低下的一个原因。在不引入内存机制的时代,有不少开发者宁可通过复杂的变成,套用一系列的循环和判断操作而避免使用游标。引入内存机制后,我们思考把游标的指向有硬盘表指向内存表进行一系列操作,游标的存储依然在内存中实现,这样既降低了游标对系统性能的影响,同时又提高了数据批量处理的效率,可谓一举两得。
1) 游标的建立
内存表的游标和普通游标一样,是一系列指针的集合,他的主体可以看作一张写满地址的内存表。内存表游标也提供两种建立方式,及索引和全检索。另外使用游标时首先要对其指向的内存表加写意向锁,避免由于删除记录等操作引起的指向错误。
2) 打开游标
根据游标的两种不同类型,打开游标也使用两种对应的方式。一种方式是打开根据索引方式检索的一个查询游标。另一种方式是打开一个全表检索的查询游标,这种方式不需要提供索引号,取而代之的是一个比较数据和其在记录中的偏移位置
3) 关闭游标
即关闭已经打开的查询游标,与关闭内存表一样,这个函数并不释放游标占用的内存。
4) 返回记录数
交易系统时常要都要统计各种分类的交易比数,为了操作员能直接去到这个值,我们需要提供对游标记录数的返回函数。
5) 获取当前游标记录
这个是游标系统的主要功能函数,用于获取当前位置的游标中的记录数据,执行原理如图1。
在游标刚刚打开的时候,取到的为游标首记录的数据。
6) 游标移动
游标移动包括上移和下移,指的是在游标中向上(或向下)移动一个游标位置指针。
2.3 索引研究
红黑树是在1972年由Rudolf Bayer发明的,又称作"对称二叉B树"[1]。它是一种高效的复杂树,一颗n结点红黑树可以在O(lg n)时间内完成查找、插入或删除操作。红黑树作为二叉查找树,它们当中每一个节点的比较值都必须大于或等于在它的左子树中的所有节点,并且小于或等于在它的右子树中的所有节点。这也确保了红黑树运作时能够快速的在树中查找给定的值。除了二叉查找树带有的一般要求,我们对任何有效的红黑树加以如下增补要求:
1) 节点是红色或黑色。
2) 根是黑色。
3) 所有叶子(外部节点)都是黑色。
4) 每个红色节点的两个子节点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色节点)。
5) 从每个叶子到根的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键属性: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。因为操作比如插入、删除和查找某个值都要求与树的高度成比例的最坏情况时间,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树[2]。一个典型的红黑树如图2。
红黑树和AVL树一样都对插入时间、删除时间和查找时间提供了最好可能的最坏情况担保。这不只是使它们在时间敏感的应用如即时应用(real time application)中有价值,而且使它们有在提供最坏情况担保的其他数据结构中作为建造板块的价值。
我们根据数据结构红黑树的原理创建了一套高效的索引机制。
2.4 内存表的并发和共享设计
我们改进了硬盘表的加锁机制使之能够适用于该内存机制,同时内存锁和硬盘锁配合使用[3]。由于内存表放于主内存中,而linux的安全保护政策是允许多个核心进程存在的,所以这样做并不能避免被事先分配给内存表的共享内存区块被某些优先级很高的系统进程所抢占,但是可以大大减少此类事情发生的可能性[4]。
2.4.1 锁机制设计
主要包括对内存表的加锁和解锁,同时提供一个进行加锁分析的功能,用于手工分析该加什么锁[5]。加锁分下列五个阶段进行:
1)内存表建立阶段,
2)内存表/索引读取阶段,
3)内存表/索引写入阶段,
4)内存表同步阶段,
5)内存表消亡阶段。
2.4.2 锁机制实现
锁机制也是由函数控制。这里的实现不包括硬盘表部分,因为这些已经由主关系数据库实现了,锁机制部分只是调用而已,真正要实现的主要部分是对内存表进行锁控制。
2.5 系统维护与监控
我们设计了内存表的监控程序来完成系统的维护与监控,它包括两个部分:一方面用于监控已经存在的内存表状态,另一方面用于监控当前关系数据库中硬盘表的状态,这个监控程序需要考虑表的总流量、瞬时流量、访问次数、平均队列响应时间等一系列参数。既可以监控未建立内存表的硬盘表,衡量其是否适宜建立内存表都很大,又可以检测关系数据库是否产生了故障。
3 总结与体会
总的来讲,该研究实现了6个方面的内容:分析和设计了一套适合交易系统和原有关系数据库的内存机制实现框架;把关系数据库的表格存储和操作搬到了内存上;采用红黑树数据结构建立了一套灵活的内存读写索引;设计了一套内存并发与共享机制;优化了内存和原硬盘数据同步读取和更新;建立了一套有效的维护和监控方案。这6个方面构成了一套完整的交易数据库内存系统。这套系统是建立在应用服务器的主内存(系统内存)中,把原先在硬盘上进行读写的一些业务操作通过高效的内存来处理,可使单表操作的速度提高一至两个数量级,从而使整个业务的效率提高几倍。而且这套系统的原理还可以用在大多数实时性高数据量大的业务关系数据库系统中,具有比较好的通用性。
参考文献
[1]陈强璋.一种高效的二叉查找树———红黑树.华东师范大学学报(自然科学版),2000(3):39—42
[2]Ford W,Topp W,等.数据结构C++语言描述—应用标准模板库(STL)(第2版).陈君译.北京:清华大学出版社,2003
[3]邹建.SQL Server2000开发与管理应用实例.北京:人民邮电出版社,2005
[4]Love R.Linux内核设计与实现(第二版).陈莉君,康华,张波,译.北京:机械工业出版社,2006
【内存系统】推荐阅读:
内存管理系统06-12
基于内存的文件系统07-21
系统内存使用率05-27
内存数据库系统09-26
Linux系统内存使用经验08-21
操作系统内存管理实验08-21
Linux系统内存使用的体会及命令解释09-08
物理内存05-08
内存优化06-22
内存结构09-03