您的位置:首页 > 编程语言 > Java开发

Java NIO 第一章 介绍(7)

2010-10-14 12:49 218 查看
1.4.4.1 内存映射文件

 
对于常规的文件IO,当用户进程使用read()或者write()系统调用来传输数据时,至少会使用一次复制操作将数据从内核中的文件页传送到用户空间的内存区域。这是因为通常在文件页和用户缓冲区中没有一一对应关系。但是,现在大多数的操作系统支持一种特殊的文件操作方式,这种方式使用户进程充分利用系统IO天然的页机制,而且完全避免了缓冲区拷贝。这种方式就是内存映射文件,如图1.6所示。
图1.6 用户内存映射到文件系统

内存映射IO使用文件系统建立一个从用户空间到可用的文件系统页的虚拟内存映射,这样做有以下几个好处:
 
l        
用户进程将文件数据当做内存,从而不再需要处理read()和write()系统调用。
l        
当用户进程处理被映射的内存空间时,产生的页错误将自动使数据从硬盘中导入到内存中。如果用户进程修改被映射的内存空间,被修改的页面将被标记为已修改,随后这些页面被刷新到磁盘中完成文件更新。
l        
操作系统的虚拟内存模块扮演了一个智能缓冲的角色,它会根据系统负载自动管理内存。
l        
数据总是页对齐的,而且不再需要进行缓冲区拷贝。
l        
大文件的映射将不需要消耗大量的内存来拷贝数据。
 
虚拟内存和磁盘IO是紧密的联系在一起的,从一些角度来说,她们只不过是同一样东西的两种不同角度而已。在处理大量数据时,你需要牢记一点。大多数的操作系统在处理页对齐和大小为页大小整数倍的数据缓冲区时,具有超出寻常的高效率。
 
 
1.4.4.2 文件锁
 
文件锁是一种约束多个进程访问同一文件的机制。锁通常被用来控制共享文件的更新,或者作为事务处理的一部分。从本质上说,文件锁是控制多个实体对共享资源的并发访问。像数据库这样的复杂应用程序通常非常依赖文件锁。
 
尽管文件锁意味着锁住整个文件,但是锁却是有细粒度的。文件区域通常被锁定到字节级别的细粒度。锁是跟一个特定的文件联系在一起的,它保护着特定的文件数据区域。因此锁可以允许不同的进程访问文件的不同区域。
 
文件锁可以分为两种:共享锁和排斥锁。多个共享锁能够同时保护同一个文件区域。而排斥锁将允许一个锁在文件区域起作用。
 
共享锁和排斥锁的一个典型的用法就是,让他们来更新被多个进程共享读操作的文件。一个希望读取文件的进程,首先需要对这个文件或文件的一部分加锁。如果第二个进程也希望读取该文件,它也需要对这个文件加锁。两个进程可以同时阅读这个文件,而不会导致相互干扰。但是,如果有第三个进程希望对这个文件进行更新,它就需要得到一个排斥锁。这时它会一直阻塞直到所有的锁(包括共享锁和排斥锁)都被释放。当它得到排斥锁时,它就可以对文件进行更新了,当然在它更新完并释放排斥锁之前其它的进程将不能得到任何的锁。这样做可以让进程在更新完文件之前所有的读取操作都不会得到执行,也保证了读取的数据保持一致。图1.7和图1.8对上面的过程进行了描述。
                            图1.7 排斥锁被共享锁阻塞

                            图1.8 共享锁被排斥锁阻塞

文件锁可以使协作式的也可以使抢占式的。协作式的锁给请求锁的进程提供了锁的信息,但是这不是被操作系统强制实行的。协作式锁取决于进程间的协作,只是给进程提供锁的建议而已。大多数的UNIX或者类UNIX操作系统提供了协作锁。有一些操作系统提供的是抢占锁或者两者都提供。
 
抢占锁是被操作系统或者文件系统强制执行的,不管进程是否意识到文件锁的存在,进程都不能访问被锁定的文件。通常微软的操作系统就是采用抢占锁。最好假设所有的锁都是协作式的,使用锁时也应该采用一致的锁来访问所有的共享资源。假设所有的锁都是协作式的是一种非常好的跨平台策略。任何使用抢占锁的应用程序将天生的不具备平台独立性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息