4.15 link、unlink函数-创建和删除硬链接

来源:互联网 发布:8848 m3手机备份数据 编辑:程序博客网 时间:2024/06/05 00:39

link函数用于创建一个指向已存在文件的新目录项。函数原型如下:

#include <unistd.h>int link(const char *existingpath, const char *newpath);

返回值:若成功则返回0,若失败则返回-1

参数:

existingpath 一个以存在文件的路径

newpath 新目录项的路径

一、目录项和硬链接

可以这么理解,不管是fat32还是ext3等文件系统,无论它的管理策略如何复杂,对于这些文件系统之下的一个文件来说都包括两个方面的属性:

数据属性和管理属性。数据属性由数据应用程序来解释,以特定模型来描述,例如网页文件就用html规范模型来描述。文件系统一般不构造这些具体模型来解释它所管理的数据,一切文件数据在文件系统看来都是一个个的0和1。

管理属性是因文件管理目的而产生的。文件系统会用具体的模型来描述文件的管理属性并做精确解释,不同的文件系统下的文件管理属性是有差别的。unix系统可以让多个文件系统同存。在具体的文件系统上层再加一层抽象文件系统,把不同的文件系统的差异屏蔽掉,抽象出一些通用模型,这个模型之一就是stat结构(参考《4.2 stat函数》)。

目录项也是文件的一种管理属性,它是为了方便我们用/tmp/myfile之类的人性化路径操作文件而设计的一种数据结构,也是文件管理属性的一个具体存储结构。

文件系统不应该主动去改变文件的数据属性,它应听从于具体应用程序去改变文件的数据属性。

文件系统可以主动改变文件的管理属性,例如你每次调用read写入数据时,文件系统会自动地把文件的最后修改时间(stat.st_mtime)给改变了。但文件系统不会没有明确指示的时候自己调用read函数乱写些数据给你的文件。

文件的管理属性在文件系统看来,最重要的作用是作为文件的一种身份标识:此文件是此文件而不是彼文件。目录项就是一个典型身份表示方式。现实上一个人可以有多个身份,比如一个技术员可以兼任技术主管。实体是一个人,身份却有两个。

目录项中除了时间、权限和路径等数据项外,还有一个数据项表明实际数据在哪里,这个数据项称之为i节点指针。自然地,我们可以创建两个具有相同i节点指针的不同目录项,都指向同一个i节点,实现一个文件两个路径。相当于一人拥有两个身份。这就是创建一个文件的硬链接。

文件系统中还有一种叫作符号链接。它与硬链接是不同的。符号链接是一个真实的文件,只是这个文件的数据属性(也就是文件的实际内容而不是i节点指针)记录了另外一个文件的路径。要找到它实际指向的文件,必须取得这个符号链接文件的全部文件数据,然后以取得的字符作为路径去查找文件的目录项才能找到实际的文件。


调用link函数创建一个新目录项时,existingpath必须是已经真实存在的,而且必须位于同一个文件系统(不仅仅是同一个操作系统)。而调用symlink函数创建符号链接时,指向的实际路径可以不存在,也可以跨越不同文件系统。

实例 x.4.15.1.c

#include <stdio.h>#include <unistd.h>int main(void){    char     existfile[] = "/tmp/myfile";    char     filelink[] = "/tmp/filelink";    char     existdir[] = "/tmp/mydir";    char     dirlink[] = "/tmp/dirlink";    if (link(existfile, filelink) < 0)        printf("link error for file:%s\n", filelink);    if (link(existdir,dirlink) < 0)        printf("link error for dir:%s\n", dirlink);        return 0;}   

编译与执行:

[root@localhost unixc]# cc x.4.15.1.c
[root@localhost unixc]# ./a.out
link error for dir:/tmp/dirlink
[root@localhost unixc]# ls -l /tmp/myfile /tmp/mydir /tmp/filelink /tmp/dirlink
ls: cannot access /tmp/dirlink: No such file or directory
----r-S--T. 3 root root   10 Nov  4 23:44 /tmp/filelink
----r-S--T. 3 root root   10 Nov  4 23:44 /tmp/myfile

/tmp/mydir:
total 0
[root@localhost unixc]#

分析:代码中试图调用link函数创建一个指向目录文件的硬链接,结束失败了。linux不允许对目录文件创建硬链接(可以创建符号链接)。


二、unlink函数

unlink函数用于删除文件的一个硬链接。函数原型:

#include <unistd.h>int unlink(const char *pathname);

返回值:若成功则返回0,若出错则返回-1

参数:

pathname 文件的一个目录项路径

调用unlink函数需要特权:必须对包含该目录项的目录具有写权限和执行权限。如果stat.st_mode中的S_ISVTX位为1,还必须具有如下权限之一:

(1)拥有该文件;

(2)拥有该目录;

(3)具有超级用户特权。

删除目录项的后果:

(1)删除一个目录项不一定删除了文件的实际数据;

(2)当且只当文件的链接计数(硬链接数量)为0时,内核会自动删掉文件内容。

(3)只有所有进程不正在使用被删除的文件且文件的链接数为0时,内核才会将文件数据删除。

(4)如果还有别进程在使用该文件,unlink不会出错,内核会自己等到其他进程(包括本进程)不使用文件时悄悄地删掉文件的实际内容。

creat或者open函数创建一个新文件的同时,也隐性地创建了该文件第一个硬链接。所以你要删除ceat函数创建的文件也是用unlink,unlink函数不仅是用于删除link函数创建的目录项,他适用于任何形式创建的目录项。

要给一个文件重命名或者移动到别的目录,方法是先创建第二个目录项,然后把第一个目录项删除掉。实际数据是不会移动的,除非他们位于不同的文件系统下。但在不同文件系统下的文件移动,又不能用link和unlink了,只能对数据进行拷贝,然后再删除原来数据,尽管他们都在一个磁盘里面都要先拷贝再删除。所以在同一个文件系统下移动文件总是要比不同文件系统下要快得多。

实例 x.4.15.2.c

#include <stdio.h>#include <fcntl.h>#include <unistd.h>int main(void){    char     pathname[] = "/tmp/myfile";    if (open(pathname, O_RDWR) == -1) {        printf("open error for %s\n", pathname);        return 1;    }    if (unlink(pathname) == -1) {        printf("unlink error for %s\n", pathname);        return 2;    }    printf("unlink succeed for %s\n", pathname);    sleep(20);    return 0;}

编译与执行:

[root@localhost unixc]# echo "123456789" > /tmp/myfile
[root@localhost unixc]# ls -l /tmp/myfile
-rw-r--r--. 1 root root 10 Nov  5 01:40 /tmp/myfile
[root@localhost unixc]# df /tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb2             18306828   3121760  14255124  18% /
[root@localhost unixc]# cc x.4.15.2.c
[root@localhost unixc]# ./a.out&
[1] 3499
[root@localhost unixc]# unlink succeed for /tmp/myfile
ls -l /tmp/myfile
ls: cannot access /tmp/myfile: No such file or directory
[root@localhost unixc]# df /tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb2             18306828   3121752  14255132  18% /
[root@localhost unixc]# df /tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb2             18306828   3121760  14255124  18% /
[1]+  Done                    ./a.out
[root@localhost unixc]# df /tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb2             18306828   3121752  14255132  18% /
[root@localhost unixc]# df /tmp
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb2             18306828   3121752  14255132  18% /
[root@localhost unixc]#


原创粉丝点击