文件系统下做底层。发过来的写请求其实没有立即完成,而是等到release 时来完成。
也就是“欺骗”上层说已经完成了。
它也就以为完成了。然后就会把另外一个命令发送过来。写入,截断,修改文件。
写入 和截断都有各自的问题。
写入时会以 修改之前的为初始版本,可见前面修改的就会被忽略掉了。
当然写入的位置会进行改变。开始写入的就是00 了。
截断因为需要知道是操作的什么文件。提供的参数只有path 和 len;
所以要从path 找到它应该操作的文件。
truncate 到不会出现写入忽略。如果截断的位置在写入中间,也会造成这样的问题。
如果新分配一个file 对象。那么也是以原始版本为基础。修改的结果还是没有把前一次考虑进去
如果采用map 记录了打开的文件。每次新打开文件。但是releas 本身没有完成,
那么查找的还是上一次的文件
但是这个文件同时也在被修改。如果锁住release。那么truncate 就会等待release 完成后进行。
他们实际要进行比较的对象是 write truncate 。但是现在变成了 truncate release 。
他们之间之前是可以同步完成的关系。
这是几个问题纠缠在一起
1、 如果truncate 保证是新对象。那么不会和release 纠缠,但是问题存在。
2、 如果truncate 使用旧有对象,那么就会和release 交互操作。可能是truncate 把文件改变了。
release 在来写,可能是release 写了。truncate 再来。
我们最终要保证什么样的顺序?
write 操作完成。至少将本地信息改变后,才能进行文件的下一次写入。
这里不能对open 进行判断,open没有标志接下来是要做什么的。可以在write 和truncate 这个类型的
操作进行操作。
现在的问题是,如果考虑到了几次写入交互的问题,那么就需要对写入进行很严格的访问限制。
这里同时要保证不会妨碍正常的并行的写入。
我们实际上这里并没有违反它的规定。
这里有另外一个原则上的问题:系统的严格程度要达到什么样
1 o w r
2 o w r
2w 应该在1r 之后。
这本身也是满足系统的要求的?
(这里有两个文件本身就是同时打开,然后相互逐一写入的。)
比如 t1 t2 都打开的文件 a
t1 t2 open 了文件。
然后t1 写了一部分,t2 写了一部分。
这个作为编程者在编程时是不应该去做的。
当然如果做,并且每次指定好文件的offset ,那么是可以不犯错误的。
从文件系统的包容性来看。我们应该支持这种最为极端的情况。
如果我们都是在一个文件爱你打开 o w r 之后,才允许另外一批的写入。
那么第二个可能就等待太久了。
如我们在写入共同一个文件的时候。系统本身的log;
本来系统的意思是o r 不管。
只是负责管理 w w 之间的关系。保证它们是一个完成后另外一个进行。
如果内容传输本身就是在w 中进行的。
那么就有1w 2w 1w 1w 2w 这种情况出现。
但是如果规定是在 r 中传输数据。
而且想要保证数据的完整性。
如果考虑在1r 之后 在进行2w
那么就是 1w 1w 1w 2w 2w
这应该算是影响了系统本身的想法。。
如果我们依然要达到这样的效果,
可行的办法是 对数据写入部分进行处理。进行所操作。
也就是那个文件。
1file -- cfile
2file -- cfile
写入都采用先定位 在写入的方式。
之前还采用过共用 file 的方式。
file
file
大家使用一个file。
在open 是搜索文件是否打开了。文件如果打开过,有对象管理了。那么就直接使用了。
1、如果两个文件是同时打开,打开的时候都不会有文件存在,但是一个完成以后。
后面一个就应该直接用前面一个的了。
这里还有,他们会同时请求这个文件的目录。
文件目录这里是否应该采用锁,锁的代价?时间是否会延长。
锁应该锁什么,所应该是锁当前这个dir ,
这里的困难就是没有办法对没有建立的对象将进行锁。
除非是设置更高粒度的锁。锁住更多的对象。
在real_read_dir 时,需要检测该目录是否已经被读取过了。
进行目录锁。
在open 时,可以放置关于路径的锁。
现在需要做到的是:
对文件的修改能够按照一定顺序的完成,我们修改了它底层的返回。破坏了请求发起的顺序。
但最终要保证顺序是和原来一样的。不能在依赖于上层的管理。要底层来自己管理。
系统本身保证了底层写入是原子的:在一个写入操作没有完成之前是不会发起另外一次写入的。
从如果算作本地内容,我们也可以认为是写入完成了的。所以我们只要让对一个文件写入所修改的对象
是同一个就可以做到修改都正确写入。
我们保证open 时已经open 的文件是指向的对象是同一个。
读操作时不会有问题,读取时,大家都是有起始位置的。(采用cache 的读取方式可能需要更多的思考,
文件多次读取的时间是否会比较长,尽量采用内存。)
在写入上面,现在面对的问题是open
问题:如果前一次的写入已经达到了release 阶段,那么我们打开时,就应该把上一次的处理完在来处理这一次的。
可能是open 时发现文件已经在release 阶段。
也可能是write tuncate 时发现文件在release 阶段。
那么我们也需要在write tuncate 时对文件进行重新生成新的对象。
两次o w* r 可能处在的时间关系,也就是看第二次write 时,第一次所处的状况。
如果是write,那么二次write 处现在被锁住了,第一次write 完成后明显该进行第二次的write。
当然第一次write 没有完毕时,是不会有第二次的请求到来。
第一次write 完毕后,会调用第一次的write 和第二次的write 竞争。
这个时候两个请求只会有一个被送达。
应该来说只有写大文件才能看出。改变测试用例。
阅读(432) | 评论(0) | 转发(0) |