分类:
2008-10-31 16:53:42
4.14 file systems
Directory entry, i-node, data-blocks
一个inode会指向所有该文件对应的data-blocks,一个directory会包含一个inode number和一个文件名。而且可以有多个directory entry它们的inode number一样,既它们都是针对这个inode的硬连接。当我们删除一个directory entry时,会称作unlink而不是remove,因为只有当该inode对应的link的数目为0时,才会将该inode与对应的data block释放。所以unlink不一定会触发删除操作。这种硬连接是在file system底层的连接。
由于directory entry里包含的是inode number,而一个文件系统将所有的inode统一编号,所以,directory entry里的inode编号在一个file system里是有意义的。所以硬连接不能跨越file system的边界。因为Inode的含义会变化。
我们使用mv命令的时候,在一个文件系统内,由于inode的数据块可以不移动,而仅仅新建一个directory entry,在新的directory entry里填好inode number和文件名,然后将老的directory entry删除就可以了。效率很高。可是,同样,跨越了file system就不行了。在windows下,由于类似inode的结构在各个分区是独立编排的,因此在分区间剪切文件时,会真正的进行数据block的复制和删除。Linux呢? 分区之间inode的编号是统一编排还是各个分区独立编排呢?
Symbol link本身与硬连接不一样,硬连接是文件系统底层的的确确的连接,而symbol link压根就是一个文件,它有自己的普通的direcory entry, 指向自己对应的inode, 而这个inode的数据块里保存了真正所指向的文件的路径。只不过在inode里有个标记,表明这个文件是个symbol link文件,那么怎么去处理它,就是文件系统上层的工作了。所以symbol link文件可以看成具有特殊语义的普通文件。
关于目录的连接数,我们知道一个目录也会对应一个inode,那么该目录的inode对应的数据块里放的都是directory entry了,那么就是这个目录里包含的字文件和目录信息,其中有个directory entry就是dot, 即’.’,就是代表了这个目录他自己,这个directory entry里会保存这个directory自己的inode编号,看着就一个一个连接。同样这个目录如果有父目录,那么父目录的directory entry里会有一个指向这个目录又是一个连接,如果该目录还有子目录,那么子目录里包含的dotdot即’..’又是一个指向该目录的directory entry。可见一个目录可以有三个连接。当然还可以更多。
4.15 link, unlink, remove, rename
#include int link(const char *existingpath, const char *newpath); |
Returns: 0 if OK, 1 on error |
Link一般来说是建立硬连接,他会在一个目录下建立directory entry来指向被连接的inode.
如果是要建立指向目录的硬连接,那么一般来说都应该是具有superuser权限,因为容易造成loop。由系统甚至不允许建立目录的硬连接。
#include int unlink(const char *pathname); |
Returns: 0 if OK, 1 on error |
Unlink会删除一个老的directory entry,如果被该directory entry指向的inode的连接数变成了0,并且该文件并没有被打开,那么就删除该inode及其数据。如果正在被打开,那么等打开该文件的process关闭打开的文件的时候(如果process自己不关闭,在process退出的时候会自动关闭所有未关闭的文件)会检查是否有文件的连接数达到了0,如果是,就会删除该文件。因此,这种技术常用来确保我们生成的临时文件在程序退出的时候被删除。如下所示:创建一个临时文件后,立马unlink它。
#include "apue.h"
#include
int
main(void)
{
if (open("tempfile", O_RDWR) < 0)
err_sys("open error");
if (unlink("tempfile") < 0) //该临时文件的inode的连接数变成了0
err_sys("unlink error");
printf("file unlinked\n");
sleep(15);
printf("done\n");
exit(0);
}
If pathname is a symbolic link, unlink removes the symbolic link, not the file referenced by the link. There is no function to remove the file referenced by a symbolic link given the name of the link. 对符号连接的unlink不会删除该符号连接所指向的文件,而仅仅是删除该符号连接文件。
对于file来说,remove和unlink是一样的操作,对于目录来说 remove和rmdir是一样的操作。有些实现不支持unlink这种操作。
4.16 symbol link
到目录的硬连接只有superuser才可以建立,并且硬连接不能跨越file system的边界。
Symbol link没有这种限制,因为他足够上层。
不同的命令,不同的函数对符号连接的处理不同,有的会follow,有的不会follow,所谓follow是指对符号连接文件的操作其实是对所指向文件的操作。
由于符号连接文件是一个真正的文件,所以他会占有自己的inode。 而硬连接只是增加了一个directory entry,不会占用inode。但是其实硬连接已经过时,基本上可以用符号连接取代了。符号连接也可以产生loop:
如:
$ mkdir foo make a new directory
$ touch foo/a create a 0-length file
$ ln -s ../foo foo/testdir create a symbolic link
$ ls -l foo
total 0
-rw-r----- 1 sar 0 Jan 22 00:16 a
lrwxrwxrwx 1 sar 6 Jan 22 00:16 testdir -> ../foo
的结果: (都是有效的文件)
foo
foo/a
foo/testdir
foo/testdir/a
foo/testdir/testdir
foo/testdir/testdir/a
foo/testdir/testdir/testdir
foo/testdir/testdir/testdir/a
建立符号连的和读取符号连接的文件:
#include int symlink(const char *actualpath, const char *sympath); |
Returns: 0 if OK, 1 on error |
#include ssize_t readlink(const char* restrict pathname, char *restrict buf,
size_t bufsize); |
Returns: number of bytes read if OK, 1 on error |
Readlink读取的是符号连接文件本身。