符号链接、硬链接、快捷方式和Junctions


    UNIX系统支持符号链接和硬链接,也许大多数人都是在学习UNIX时第一次接触这两个概念的。DOS当初过于简单,自然也不支持类似的概念。到了 Windows的年代,产生了广为使用的快捷方式。到Windows NT的时候,微软逐步加入了对硬链接的支持。当然Windows中的实现还是不完全和UNIX一致。

1、UNIX中的符号链接(Symbolic links),可以链接目录或文件、可以跨文件系统。创建符号链接时,不会增加目标文件的引用计数。删除目标文件时,符号链接仍然存在,当然在使用它的时候会发现失效了。

我们在Linux下做个实验:

$ touch foo
$ ls -l foo
-rw-rw-r– 1 uniware uniware 0 Mar 8 15:26 foo

$ ln -s foo foo1
$ ls -l foo*
-rw-rw-r– 1 uniware uniware 0 Mar 8 15:26 foo
lrwxrwxrwx 1 uniware uniware 3 Mar 8 15:27 foo1 -> foo

$ ln -s foo1 foo1_1
$ ls -l foo*
-rw-rw-r– 2 uniware uniware 0 Mar 8 15:26 foo
lrwxrwxrwx 1 uniware uniware 3 Mar 8 15:27 foo1 -> foo
lrwxrwxrwx 1 uniware uniware 4 Mar 10 13:04 foo1_1 -> foo1

$ mkdir bar
$ ls -ld bar
drwxrwxr-x 2 uniware uniware 4096 Mar 8 15:28 bar

$ ls -ld bar*
drwxrwxr-x 2 uniware uniware 4096 Mar 8 15:28 bar
lrwxrwxrwx 1 uniware uniware 3 Mar 8 15:29 bar1 -> bar

2、UNIX中的硬链接(Hard links),只能链接文件、不能链接目录,而且不能跨文件系统。创建链接时,将增加目标文件的引用计数。删除目标文件或链接文件时都会导致引用计数减少。

$ ln foo foo2
$ ls -l foo*
-rw-rw-r– 2 uniware uniware 0 Mar 8 15:26 foo
lrwxrwxrwx 1 uniware uniware 3 Mar 8 15:27 foo1 -> foo
-rw-rw-r– 2 uniware uniware 0 Mar 8 15:26 foo2

$ ln foo foo2_2
$ ls -l foo*
-rw-rw-r– 3 uniware uniware 0 Mar 8 15:26 foo
-rw-rw-r– 3 uniware uniware 0 Mar 8 15:26 foo2
-rw-rw-r– 3 uniware uniware 0 Mar 8 15:26 foo2_2

$ ln bar bar2
ln: `bar’: hard link not allowed for directory

3、Windows中的硬链接(Hard links),只能链接文件、不能链接目录,而且不能跨文件系统。创建链接时,也会增加目标文件的引用计数(MSDN说最大可创建的硬链接数为 1023)。这个和UNIX的硬链接类似。不过只能在NTFS文件系统中使用。创建硬链接的API为CreateHardLink()。

请看测试程序:

/* CreateHardLink() is supported for version >= 0x500 */
#define _WIN32_WINNT 0x500

/* defined for UNICODE version */
#define UNICODE
#define _UNICODE

#include #include #include #include

int _tmain(void)
{
    HANDLE hFile;
    BOOL fCreatedLink;
    TCHAR pszNewLinkName[MAX_PATH];
    TCHAR pszExistingFileName[MAX_PATH];
    INT i = 0;

    _tcscpy(pszExistingFileName, _T(“foo.dat”));
    hFile = CreateFile(pszExistingFileName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        _tprintf(_T(“CreateFile(): %d\n”), GetLastError());
        exit(1);
    }

    CloseHandle(hFile);

    for ( ; ; )
    {
        _stprintf(pszNewLinkName, _T(“foo_link%d”), i);

        fCreatedLink = CreateHardLink(pszNewLinkName,
            pszExistingFileName,
            NULL);
            if (!fCreatedLink)
        {
            _tprintf(_T(“GetLastError(): %d\n”), GetLastError());
            break;
        }

        i++;
    }

    _tprintf(_T(“Number of hard links: %d\n”), i);
    getchar();

    exit(0);
}

正常运行后的结果应该是:

GetLastError(): 1142
Number of hard links: 1023

其中错误号1142的含义是“试图在文件上创建超过文件系统支持的链接数。”。

4、Windows中的快捷方式(Shortcuts),可以指向文件或目录,也可以跨文件系统。符号链接仍然存在,当然在使用它的时候会发现失效了。它非常类似于UNIX的符号链接。

5、Windows中还有一个特殊的东西:Junctions。它只能指向目录,也可以跨本机的文件系统,但不能跨网络文件系统。它类似于UNIX下的Mount。不过也只能在NTFS文件系统中使用。MSDN的知识库文章 “How to Create and Manipulate NTFS Junction Points” 说明了如何用工具操纵Junctions,不过要在程序中使用Junctions,还是非常麻烦。这里有个很好的例子: Reparse points and junctions

    不管是符号链接、硬链接,还是Junctions、Mount,都会给用户带来一定程序的方便,也会给我们带来很多意想不到的麻烦。比如说,很多时候我们 都需要遍历一个目录,并对遇到的目录或文件做些操作。有时我们是在遍历时修改文件的属性,有时是修改它的名字,有时是想改变其内容,还有的时候我们需要计 算文件/目录的大小。符号链接、硬链接等概念会可能我们的操作带来不尽的烦恼。 “Computing the size of a directory is more than just adding file sizes” 还指出了更多需要注意的问题。


Copyright 2000-2006,zedware_at_gmail_dot_com
Last modified on Thursday, 2006-05-18

Written on May 18, 2006