分类: 系统运维
2012-03-28 13:51:40
一个符号链接是一个文件的间接指针,不像上节的硬链接--直接指向文件的i-node。符号链接用来解决硬链接的限制。
1、硬链接通常需要链接和文件处在同一个文件系统上。
2、只有超级用户才能创建目录的硬链接。
符号链接和它指向的文件没有文件系统的限制,任何人都可以创建一个目录的符号链接。符号链接被典型用来把一个文件或整个目录结构移到系统的另一个位置。
符号链接在4.2BSD上引入,之后被SVR4支持。
当使用通过名字表示文件的函数时,我们问题需要知道函数是否解析一个符号链接。如果函数解析一个符号链接,函数的路径名参数就表示符号链接指向的文件。否则,路径名参数表示符号链接本身,而不是链接指向的文件。下表总结了本章函数是否解析一个符号链接:
各种函数对待符号链接的方式 | ||
函数 | 不解析符号链接 | 解析符号链接 |
access | * | |
chdir | * | |
chmod | * | |
chown | * | * |
creat | * | |
exec | * | |
lchown | * | |
link | * |
在Linux的早期版本(在2.1.81之前),chown没有解析符号链接。从2.1.81之后,chown开始解析符号链接。在FreeBSD
5.2.1和Mac OS X
10.3上,chown解析符号链接。(4.4BSD之前,chown没有解析符号链接,但这在4.4BSD上得以改变。)在Solaris
9,chown同样解析符号链接。所有的这些平台都提供一个lchown的实现来改变符号链接本身的属主。
上表中的一个例外是当open函数在O_CREAT和O_EXCL同时被设置时被调用。在这种情况下,如果路径名是一个符号链接,open会失败,errno被设为EEXIST。这种行为是为了关闭安全漏洞以便有权限的进程不会被愚弄导致写入一个错误文件。
使用符号链接有可能把回路引进文件系统。当它发生时,多数查询路径名的函数返回一个ELOOP的errno。考虑以下命令:
$ mkdir foo
$ touch foo/a
$ ln -s ../foo foo/testdir
$ ls -l foo
总用量 0
-rw-r--r-- 1 tommy tommy 0 2012-02-22 17:21 a
lrwxrwxrwx 1 tommy tommy 6 2012-02-22 17:22 testdir -> ../foo
这些命令创建了一个目录foo,它包含文件a,还有一个指向foo的符号链接。这样便产生了一个回路。如果使用Solaris的ftw标准函数来遍历文件结构,打印所有碰到的路径名,输出为:
foo
foo/a
foo/testdir
foo/testdir/a
foo/testdir/testdir/a
foo/testdir/testdir
foo/testdir/testdir/testdir/a
(更多的行直到我们遇到ELOOP错误。)
在4.21节,我们会提供我们自己的ftw函数的版本,使用lstat而不是stat,来避免解析符号链接。
同样使用Linux上的tree命令可以看到:
$ tree -l foo
foo
├── a
└── testdir -> ../foo [recursive, not followed]
在Linux上的ftw函数使用lstat,所以不会有上述行为发生。
这种格式的回路很容易删除。我们可以unlink文件foo/testdir,因为unlink不会解析一个符号链接。然后如果我们创建一个这种类型的回路的硬链接,它的删除将会困难的多。这是为什么除非进程有超级用户权限,否则link函数不会硬链接一个目录。
事实上,Rich Stevens(第一版的作者)在原版中写这节时在他自己的系统上作过实验。文件系统崩溃了,而且普通的fsck工具也不能修好。需要不被赞成使用的工具clri和dcheck来修复文件系统。
目录硬链接的需求很早之前就有了。有了符号链接和mkdir函数,任何不再需要创建目录的硬链接了。
当我们打开一个文件时,如果传入open的路径名是一个符号链接,open解析这个链接到指定的文件。如果指向的文件不存在,open返回错误表明它不能打开这个文件。这会使不熟悉符号链接的用户困惑。比如:
$ ln -s /no/such/file/ myfile
$ ls myfile
myfile
$ cat myfile
cat: myfile: 没有那个文件或目录
$ ls -l myfile
lrwxrwxrwx 1 tommy tommy 14 2012-02-22 17:45 myfile -> /no/such/file/