2010年10月28日

覆盖的不同方式

下面是我和一朋友的对话,里面具体说是CP和MV不同的覆盖方式。
me: 请教您一问题:目录下有一个有内容的message文件,当我在touch message时,没任何提示,直接回车。当我打开message的时候,发现还是原来的文件,那我touch的文件到哪里去了?
XX: touch了message了呀
touch不是清空文件呀
你是不是想把message文件清空?
me: 对,我的意思是要新建一个文件
不过跟message重名而已
我是想用新的文件覆盖旧的文件
XX: touch的意思是: 如果有文件存在, 只是更新一下文件的时间,
当文件不存在时, 才会创建文件
me: 只是更新时间啊!
XX: 嗯。清空的话, 可以使用: echo "" > message
>才会写文件
me: 对啊,我刚才看了一下,真的只更新了时间
me: 不是这样的,我是不明白如果一个同名的文件覆盖同名的文件是直接删除文件呢还是文件还是存在的?
是直接删除旧的文件还是旧文件还存在,只是不可见?
XX: 重新写指定的文件。
写完后, 内容就变化 了
me: 那么说,新的文件会在旧文件里面写内容,不过旧的文件内容依然存在,是不是这样?
me: 我懂了,覆盖只是将文件里面的数据给更新,而旧文件里面的内容将会被新文件给替换了
XX's new status message - I'm not here right now 4:53 PM
me: 如果新文件里面没有内容,覆盖后message文件里面也是没内容的
这是CP的结果
XX: 就是open和write函数。
me: MV的结果就不同了。
XX: 也是一样的。 如果是同名的意义是一样的。
me: 不一样的,MV后I节点改变了
CP的时候I节点却没有变
MV是不是将旧文件删除了然后将新文件放进去呢?
XX: 不是。
me: 是的,我在FreeBSD里面测试过了,的确改变了!
me: MV的结果就是将文件所在的block移到新的目录。
XX: 嗯。 是不同, 但是也不是你说的“block移到新目录“
me: 我是觉得一个文件就是一个存放数据的块而已,而这个块就是由i节点就是这个块的门牌而已,那这个i节点移到新的地方,那里面的数据块也会移过去
这是我个人理解
me: 要么就是message所在的文件夹修改message的节点,使其指到新的数据块中
XX: 这里有两种情况, :两个文件是否在同一分区
每个分区有自己的inode列表
[jessinio@niowork tmp]$ ls -i show
24969635 show
[jessinio@niowork tmp]$ ls -i do.sh
24969340 do.sh
[jessinio@niowork tmp]$ mv show do.sh
[jessinio@niowork tmp]$ ls -i do.sh
24969635 do.sh
这个例子是同一个分区的, 只是修改一个入口inode
[jessinio@niowork tmp]$ ls -i /boot/newfile
6025 /boot/newfile
[jessinio@niowork tmp]$ ls -i do.sh
24969635 do.sh
[jessinio@niowork tmp]$ sudo mv /boot/newfile do.sh
[jessinio@niowork tmp]$ ls -i do.sh
24969282 do.sh
这个例子是不同分区的,
有一个新的inode
XX: 不同分区的情况下, 才是把旧的文件删除。
你说到了一种。
不错。
有进步
使用strace这个命令可以清楚地看出mv命令都在做了些什么事情。
不知道freeBSD下使用什么工具可以知道mv到底干了些什么事。
XX's new status message - 又一次讨论问题讨到这么晚~~~~ 5:18 PM
me: FreeBSD里面也有strace这个命令
XX: 嗯。那就行
me: 不过要安装才可以的
XX: 这个工具应该是GPL的, 所以需要安装。
me: 照你这么说就是在不同分区中,mv一次就是将数据块稳到了被覆盖的文件的分区那边对啊?
XX: 数据块是“移动"不了的。
只有重新把数据都读出来, 写到新的文件上, 然后再把旧的文件删除
me: 原来这样!
是作删除然后新建
XX: 你看看下面的信息:
当我运行: strace mv /boot/newfile do.sh
mv命令首先rename("/boot/newfile", "do.sh") = -1 EXDEV (Invalid cross-device link)
但是出错了, 因为是在不同的分区
然后unlink("do.sh")
删除文件后,
open("do.sh", O_WRONLY|O_CREAT, 0100644) = 4
me: 那么在同一分区内进行MV覆盖,旧的文件是不是被删除了呢?
XX: 你说的“旧的文件“是指哪个?
mv old new
old这个文件当然是要删除的了
me: 嗯!