手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

第三章--文档I/O

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!


。

在SVR4中,v[CD#*2]node代换了SVR3中的和文档系统类型无关的i[CD#*2]node结构

。

假如两个单独进程各自打开了同一文档,则有图33中所示的安排。我们假定第一

个进程使

该文档在文档描述符3上打开,而另一个进程则使此文档在文档描述符4上打开。打

开此文档

的每个进程得到一个文档表项,但对一个给定的文档只有一个v[CD#*2]node表项。

每个进程

都有自己的文档表项的一个理由是:这种安排使每个进程都有他自己的对该文档的

当前位移

量。

图33〓两个单独进程各自打开同一个文档

给出了这些数据结构后,我们现在对前面所述的操作作进一步说明。

·在完成每个write后,在文档表项中的当前文档位移量即增加所写的字节数。如

果这使当

前文档位移量超过了当前文档长度,则在i〖CD#*2〗node表项中的当前文档长度被

配置为当

前文档位移量(也就是该文档加长了)。

·假如用O[CD#*2]APPEND标志打开了一个文档,则相应标志也被配置到文档表项的

他自己的

文档表项,在其中也就有他自己的当前文档位移量。但是,当多个进程写同一文档

时,则可

能产生非预期的结果。为了说明如何避免这种情况,我们需要理解原子操作的概念

。

311〓原子操作

添写至一个文档

考虑一个进程,他要将数据添写到一个文档尾端。较早的Unix版本并不支持open的

O[CD#*2]

APPEND选择项,所以程式被编写成下列形式:

if(lseek(fd,OL,2)<0)〓〓〓〓〓〓〖WB〗/*定位至文档尾端*/

err[CD#*2]sys("lseek error");

if (write(fd,buff,100)!=100)〖DW〗/*写*/

err[CD#*2]sys("write error");

对单个进程而言,这段程式能正常工作,但若有多个进程使用这种技术添写到同一

文档中,

则就会产生问题。(假如此程式由多个进程同时执行,各自将消息添写到一个日记

文档中,

则就会产生这种情况。)

假定有二个单独的进程A和B,都对同一文档进行添写操作。每个进程都已打开了该

文档,但

未使用O[CD#*2]APPEND标志。此时各数据结构之间的关系如图33中所示相同。每

个进程都

有他自己的文档表项,但是共享一个v[CD#*2]node表项。假定进程A调用了lseek,

他将对于

进程A的该文档当前位移量配置为1500字节(当前文档尾端处)。然后系统核转换进

程使进程B

运行。进程B执行lseek,也将其对该文档的当前位移量配置为1500字节(当前文档

尾端处)。

然后B调用write,他将B的该文档当前文档位移量增至1600。因为该文档的长度已

经增加了

,所以系统核对v[CD#*2]node中的当前文档长度更新为1600。然后,系统核又进行

进程转换

使进程A恢复运行。当A调用write时,就从其当前文档位移量(1500)处将数据写到

文档中去

。这样也就代换了进程B刚写到该文档中的数据。

这里的问题出在逻辑操作"空档到文档尾端处,然后写"使用了二个分开的函数调用

。解决

问题的方法是使这两个操作对于其他进程而言成为一个原子操作。任何一个需要多

于1个函

数调用的操作都不能成为原子操作,因为在两个函数调用之间,系统核有可能会临

时挂起该

进程(正如我们前面所假定的)。

Unix提供了一种方法使这种操作成为原子操作,其方法就是在打开文档时配置O[C

D#*2]APPE

ND标志。正如我们在前一节中所说明的,这就使系统核在每次对这种文档进行写之

前,都将

进程的当前位移量配置到该文档的必端处,于是在每次写之前就不再需要调用lse

ek。

创建一个文档

在对open函数的O[CD#*2]CREAT和O[CD#*2]EXCL选择项进行说明时,我们已见到了

另一个有

关原子操作的例子。当同时指定这两个选择项,而该文档又已存在时,open将失

败。我们

曾提及检查该文档是否存在连同创建该文档这两个操作是作为一个原子操作执行的

。假如我

们没有这样一个原子操作,那么可能会编写下列程式段:

if ((fd=open(pathname,O[CD#*2]WRONLY)) <0)

〓〓if (errno==ENOENT) {

〓〓〓〓if ((fd=creat (pathname,mode))<0)

〓〓〓〓〓〓err[CD#*2]sys("creat error");

〓〓} else

〓〓〓〓err[CD#*2]sys("open error");

假如在打开和创建之间,另一个进程创建了该文档,那么就会发生问题。假如在这

两个函数

调用之间,另一个进程创建了该文档,而且又向该文档写进了一些数据,那么执行

这段程式

中的creat时,刚写上去的数据就会被擦去。将这两者合并在一个原子操作中,此

种问题也

就不会产生。

一般而言,术语原子操作指的是由多步组成的操作。假如该操作原子地执行,则或

者执行完

任何步,或一步也不执行,没有可能只执行任何步的一个子集。在415节述及

link函数

连同在123节中述及记录锁时,我们还将讨论原子操作。

312〓dup和dup2函数

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!