十三、文件和目录——软链接和硬链接

13.1 软链接和硬链接介绍

13.1.1 软硬链接的创建

  通过 ln 命令可以对文件创建软硬链接

  创建硬链接 

  

  2 表示链接数

  创建软链接

  

  通过 ls -l  命令显示的文件类型为 l,表示文件类型为符号链接

  • 若删除原始文件,对硬链接来说依然可以查看到文件内容,只不过链接数会减1,对软链接来说,则链接依然存在,但是查看不到文件内容了,用 cat  和 more 命令的时候,会提示没有哪个文件或目录。

13.1.2 软硬链接在Linux系统中的存放

  创建硬链接的时候,只是多创建了一个目录项,并不会创建一个 i 节点和数据块,然后链接数 +1。只有直到硬链接数为0的时候,才会释放这个文件,即真正的删除。

  创建硬链接,数据块存放的是源文件的路径,所以当源文件删除后,就找不到软链接的内容了。但是 i 节点和数据块还存在。软链接的链接数永远都是1。

  

13.2 硬链接函数

  • 硬链接创建条件
    • 针对文件创建链接,无法对目录进行创建,除非是 root 用户
    • 必须是同一个分区
    • 只有超级用户才能对目录建立连接
  • 文件删除条件
    • 链接计数为0
    • 无其他进程打开该文件  

13.2.1 创建链接-link 函数

  link(建立文件连接)
  相关函数 symlink,unlink

1 #include <unistd.h>
2 int link (const char * oldpath, const char * newpath);
  • 函数说明
    • link()以参数 newpath 指定的名称来建立一个新的连接(硬连接)到参数 oldpath 所指定的已存在文件。
    • 如果参数 newpath 指定的名称为一已存在的文件则不会建立连接。
  • 函数功能:
    • 创建一个指向现存文件的连接(硬链接)
  • 附加说明
    • link()所建立的硬连接无法跨越不同文件系统,如果需要请改用 symlink()。
  • 返回值
    • 成功则返回0,失败返回-1,错误原因存于errno。
  • 附加说明
    • link()所建立的硬连接无法跨越不同文件系统,如果需要请改用 symlink()。
  • 错误代码
    • EXDEV 参数 oldpath 与 newpath 不是建立在同一文件系统。
    • EPERM 参数 oldpath 与 newpath 所指的文件系统不支持硬连接
    • EROFS 文件存在于只读文件系统内
    • EFAULT 参数 oldpath 或 newpath 指针超出可存取内存空间。
    • ENAMETOLLONG 参数 oldpath 或 newpath 太长
    • ENOMEM 核心内存不足
    • EEXIST 参数 newpath 所指的文件名已存在。
    • EMLINK 参数 oldpath 所指的文件已达最大连接数目。
    • ELOOP 参数 pathname 有过多符号连接问题
    • ENOSPC 文件系统的剩余空间不足。
    •   EIO I/O 存取错误。 

13.2.2 删除链接

  unlink(删除文件)
  相关函数 link,rename,remove

1 #include <unistd.h>
2 int unlink(const char * pathname);
  • 函数说明
    • unlink()会删除参数 pathname 指定的文件。
    • 如果该文件名为最后连接点,但有其他进程打开了此文件,则在所有关于此文件的文件描述词皆关闭后才会删除。
    • 如果参数 pathname 为一符号连接,则此连接会被删除。
  • 函数功能:
    • 删除 pathname 指定的硬链接(源文件和指定的硬链接文件都可以),并将由 pathname 所引用的文件链接计数减1  
  • 返回值
    • 成功则返回0,失败返回-1,错误原因存于errno
  • 错误代码
    • EROFS 文件存在于只读文件系统内
    • EFAULT 参数 pathname 指针超出可存取内存空间
    • ENAMETOOLONG 参数 pathname 太长
    • ENOMEM 核心内存不足
    • ELOOP 参数 pathname 有过多符号连接问题
    • EIO I/O 存取错误

13.2.3 remove 函数

  remove(删除文件)
  相关函数 link,rename,unlink

1 #include <stdio.h>
2 int remove(const char * pathname);
  • 函数说明
    • remove()会删除参数 pathname 指定的文件。
    • 如果参数 pathname 为一文件,则调用 unlink() 处理,若参数 pathname 为一目录,则调用 rmdir() 来处理。请参考 unlink() 与 rmdir()。
    • 对于文件,remove 的功能与 unlink 相同
    • 对于目录,remove 的功能与 rmdir 相同
  • 函数功能:
    • 解除一个文件或目录的链接
  • 返回值
    • 成功则返回0,失败则返回-1,错误原因存于errno。
  • 错误代码
    • EROFS 欲写入的文件存在于只读文件系统内
    • EFAULT 参数 pathname 指针超出可存取内存空间
    • ENAMETOOLONG 参数 pathname 太长
    • ENOMEM 核心内存不足
    • ELOOP 参数 pathname 有过多符号连接问题
    • EIO I/O 存取错误

13.2.4 rename 函数

  rename(更改文件名称或位置)
  相关函数 link,unlink,symlink

1 #include <stdio.h>
2 int rename(const char * oldpath, const char * newpath);
  • 函数说明
    • rename() 会将参数 oldpath 所指定的文件名称改为参数 newpath 所指的文件名称。若 newpath 所指定的文件已存在,则会被删除。
  • 函数功能:
    • 文件或目录更名
  • 返回值
    • 执行成功则返回0,失败返回-1,错误原因存于errno

13.2.5 例子

  (1)硬链接的创建

  file_hardlink.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <fcntl.h>
 5 #include <string.h>
 6 
 7 int main(int argc, char *argv[])
 8 {
 9     if(argc < 0) {
10         fprintf(stderr, "usage:%s srcfile files\n", argv[0]);
11         exit(1);
12     }
13 
14     int i;
15 
16     for(i = 2; i < argc; i++){
17         if(link(argv[1], argv[i]) < 0) {
18             perror("link error");
19             continue;
20         }
21     }
22 
23     printf("create success\n");
24     return 0;
25 }

  编译执行如下:

  

  

13.3 软链接(即符号链接)

13.3.1 创建软链接

(1)创建软链接

  symlink(建立文件符号连接)
  相关函数 link,unlink

1 #include <unistd.h>
2 int symlink( const char * oldpath, const char * newpath);
  • 函数说明
    • symlink() 以参数 newpath 指定的名称来建立一个新的连接(符号连接)到参数 oldpath 所指定的已存在文件。
    • 参数 oldpath 指定的文件不一定要存在,如果参数 newpath 指定的名称为一已存在的文件则不会建立连接。
    • 创建符号链接并不要求 oldpath 的存在
    • 可以跨文件系统建立符号链接
    • 软链接可以针对目录进行创建
  • 函数功能
    • 创建一个符号链接(软链接)
  • 返回值
    • 成功则返回0,失败返回-1,错误原因存于errno。
  • 错误代码
    • EPERM 参数 oldpath 与 newpath 所指的文件系统不支持符号连接
    • EROFS 欲测试写入权限的文件存在于只读文件系统内
    • EFAULT 参数 oldpath 或 newpath 指针超出可存取内存空间。
    • ENAMETOOLONG 参数 oldpath 或 newpath 太长
    • ENOMEM 核心内存不足
    • EEXIST 参数 newpath 所指的文件名已存在。
    • EMLINK 参数 oldpath 所指的文件已达到最大连接数目
    • ELOOP 参数 pathname 有过多符号连接问题
    • ENOSPC 文件系统的剩余空间不足
    • EIO I/O 存取错误

(2)读取软链接

  readlink(取得符号连接所指的文件)
  相关函数 stat,lstat,symlink

1 #include <unistd.h>
2 ssize_t readlink(const char * path ,char * buf,size_t bufsiz);
  • 函数说明
    • readlink()会将参数 path 的符号连接内容存到参数 buf 所指的内存空间,返回的内容不是以 NULL 作字符串结尾,但会将字符串的字符数返回。若参数 bufsiz 小于符号连接的内容长度,过长的内容会被截断。
  • 函数功能
    • 打开该链接本身,并读该链接中的名字(源文件的路径)
  • 返回值
    • 成功则返回读到的字节数,失败则返回-1,错误代码存于errno。
  • 错误代码
    • EACCESS 取文件时被拒绝,权限不够
    • EINVAL 参数 bufsiz 为负数
    • EIO I/O 存取错误。
    • ELOOP 欲打开的文件有过多符号连接问题。
    • ENAMETOOLONG 参数 path 的路径名称太长
    • ENOENT 参数 path 所指定的文件不存在
    • ENOMEM 核心内存不足
    • ENOTDIR 参数 path 路径中的目录存在但却非真正的目录。

13.3.2 例子

  file_link.c

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <fcntl.h>
 4 #include <stdlib.h>
 5 #include <errno.h>
 6 #include <unistd.h>
 7 
 8 int main(int argc, char *argv[])
 9 {
10     if(argc < 3) {
11         fprintf(stderr, "usage:%s srcfile linkfiles\n", argv[0]);
12         exit(1);
13     }
14 
15     //对源文件创建符号链接(软链接)
16     if(symlink(argv[1], argv[2]) < 0) {
17         perror("symlink error");
18         exit(1);
19     }
20 
21     //读取软链接引用的源文件的内容
22     char buff[4096];
23     ssize_t size;
24     memset(buff, 0, sizeof(buff));
25     int fd = open(argv[2], O_RDONLY);
26     if(fd < 0) {
27         perror("open error");
28         exit(1);
29     }
30 
31     if((size = read(fd, buff, sizeof(buff))) < 0) {
32         perror("read error");
33         exit(1);
34     } else {
35         write(STDOUT_FILENO, buff, size);
36     }
37 
38     printf("\n");
39 
40     //读取软链接本身的内容
41     memset(buff, 0, sizeof(buff));
42     if((size = readlink(argv[2], buff, sizeof(buff))) < 0) {
43         perror("readlink error");
44         exit(1);
45     } else {
46         write(STDOUT_FILENO, buff, size);
47     }
48 
49     printf("\n");
50 
51     return 0;
52 }

   编译执行

  

posted @ 2018-05-20 22:39  游戏进行中  阅读(969)  评论(0编辑  收藏  举报