硬链接和符号链接

1.硬链接

每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向想要读取的文件,必须要经过目录记录的文件名来指向到正

确的 inode 号码才能读取。也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。那么想一想, 有没有可能

有多个档名对应到同一个 inode 号码呢?有的!那就是 hard link 的由来。 所以简单的说:hard link 只是在某个目录下新增一

笔档名链接到某 inode 号码的关连记录而已。

举个例子来说,假设我系统有个 /root/crontab 他是 /etc/crontab 的实体链接,也就是说这两个档名连结到同一个 inode , 自

然这两个文件名的所有相关信息都会一模一样(除了文件名之外)。实际的情况可以如下所示:

[[email protected] ~]# ln /etc/crontab .   <==创建实体链接的命令
[[email protected] ~]# ll -i /etc/crontab /root/crontab
1912701 -rw-r--r-- 2 root root 255 Jan  6  2007 /etc/crontab
1912701 -rw-r--r-- 2 root root 255 Jan  6  2007 /root/crontab

你可以发现两个档名都连结到 1912701 这个 inode 号码,所以您瞧瞧,是否文件的权限/属性完全一样呢? 因为这两个『档名』

其实是一模一样的『文件』啦!而且你也会发现第二个字段由原本的 1 变成 2 了! 那个字段称为『连结』,这个字段的意义

为:『有多少个档名链接到这个 inode 号码』的意思。 如果将读取到正确数据的方式画成示意图,就类似如下画面:

上图的意思是,你可以透过 1 或 2 的目录之 inode 指定的 block 找到两个不同的档名,而不管使用哪个档名均可以指到 real 那个

inode 去读取到最终数据!那这样有什么好处呢?最大的好处就是『安全』!如同上图中, 如果你将任何一个『档名』删除,其

实 inode 与 block 都还是存在的! 此时你可以透过另一个『档名』来读取到正确的文件数据喔!此外,不论你使用哪个『档名』

来编辑, 最终的结果都会写入到相同的 inode 与 block 中,因此均能进行数据的修改!

一般来说,使用 hard link 配置链接文件时,磁盘的空间与 inode 的数目都不会改变! 我们还是由图 2.2.1 来看,由图中可以知道,

hard link 只是在某个目录下的 block 多写入一个关连数据而已,既不会添加 inode 也不会耗用 block 数量。

创建现有文件的硬链接是使用link函数。函数声明如下:

[cpp] view plaincopy

  1. <pre name="code" class="cpp">#include <unistd.h>
  2. int link(const char* existingpath, const char* newpath);</pre>

如果成功则返回0,出错则返回-1.

删除一个现有文件的硬链接是使用unlink函数,函数声明如下:

//删除哪一个目录项呢

[cpp] view plaincopy

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

如果成功则返回0,出错则返回-1.

实践:

[cpp] view plaincopy

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(void){
  4. if(link("a","a2")<0){
  5. perror("unlink");
  6. }
  7. return 0;
  8. }

运行结果:

[email protected]:~/apue$ ll -i a
939363 -rw-rw-r-- 1 yan yan 0 Jul 10 07:55 a
[email protected]:~/apue$ ./a.out
[email protected]:~/apue$ ll -i a a2
939363 -rw-rw-r-- 2 yan yan 0 Jul 10 07:55 a
939363 -rw-rw-r-- 2 yan yan 0 Jul 10 07:55 a2

如果link的是一个目录,结果会如何:

[cpp] view plaincopy

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(void){
  4. if(link("test","test2")<0){
  5. perror("link");
  6. }
  7. return 0;
  8. }

运行结果:

drwxrwxr-x  2 yan yan 4096 Jul 10 07:58 test/

[email protected]:~/apue$ ./a.out
link: Operation not permitted
[email protected]:~/apue$ su
Password:
[email protected]:/home/yan/apue# ./a.out
link: Operation not permitted

[cpp] view plaincopy

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(void){
  4. if(unlink("a")<0){
  5. perror("unlink");
  6. }
  7. return 0;
  8. }

运行结果:

[email protected]:~/apue$ ll -i a a2
939363 -rw-r--r-- 2 root root 0 Jul 10 08:09 a
939363 -rw-r--r-- 2 root root 0 Jul 10 08:09 a2

[email protected]:~/apue$ ./a.out
[email protected]:~/apue$ ll a
ls: cannot access a: No such file or directory
[email protected]:~/apue$ ll -i a2
939363 -rw-rw-r-- 1 yan yan 0 Jul 10 07:55 a2

如果unlink是一个目录会怎样?

unlink: Is a directory1

看来无法使用unlink删除目录。

只有当硬链接计数达到0时,该文件的内容才可被删除;只要有进程打开了该文件,其内容也不能删除。关闭一个文件时,内核

首先检查打开该文件的进程数,如果达到0,然后再检查其硬链接数,如果也是0,则删除该文件内容。

下面是unlink的一种应用,确保程序创建的临时文件不会被遗留下来。

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. int main(void){
  4. int fd;
  5. char buf[10];
  6. if((fd = open("tempfile",O_RDWR)) <0){
  7. perror("open");
  8. return -1;
  9. }
  10. if(unlink("tempfile") < 0){
  11. perror("unlink");
  12. return -1;
  13. }
  14. printf("unlink ok\n");
  15. int readnum = read(fd,buf,10);
  16. printf("read num:%d,read content:%s\n",readnum,buf);
  17. sleep(15);
  18. printf("done\n");
  19. return 0;
  20. }

运行结果:

[email protected]:~/apue$ cat tempfile
123
[email protected]:~/apue$ ./a.out
unlink ok
read num:4,read content:123
^Z
[2]+  Stopped                 ./a.out
[email protected]:~/apue$ ll tempfile
ls: cannot access tempfile: No such file or directory
[email protected]:~/apue$ fg
./a.out
done
[email protected]:~/apue$ ll tempfile
ls: cannot access tempfile: No such file or directory

进程用open或者creat创建一个文件,然后立即调用unlink,因为该文件仍旧是打开的,所以不会将其内容删除,只有当进程

关闭该文件或者终止时,该文件才会被删除。 //有一个信号通知?

删除一个文件可以使用remove函数,函数声明如下:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. int remove(const char* pathname);

如果成功,则返回0,失败则返回-1。

实践:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. int main(void){
  3. if(remove("a")<0){
  4. perror("remove");
  5. }
  6. return 0;
  7. }

运行结果:

[email protected]:~/apue$ ll a
-rw-rw-r-- 1 yan yan 0 Jul 10 09:44 a
[email protected]:~/apue$ ./a.out
[email protected]:~/apue$ ll a
ls: cannot access a: No such file or directory
[email protected]:~/apue$ mkdir a
[email protected]:~/apue$ ll
total 80
drwxrwxr-x  4 yan  yan  4096 Jul 10 09:44 ./
drwx---rwx 25 yan  yan  4096 Jul 10 09:42 ../
drwxrwxr-x  2 yan  yan  4096 Jul 10 09:44 a/
[email protected]:~/apue$ ./a.out
[email protected]:~/apue$ ll
total 76
drwxrwxr-x  3 yan  yan  4096 Jul 10 09:44 ./
drwx---rwx 25 yan  yan  4096 Jul 10 09:42 ../

不像unlink函数,remove函数可以删除目录。

2.符号链接

符号链接类似于windows中的快捷方式,它是一个新文件,有自己的i节点有的函数对符号链接文件进行操作并不能反映到其链

接的文件上去,下表是各个函数对符号链接的处理。

*跟随符号链接是指跟随符号链接到达实际的文件

下面2个函数是对符号链接文件进行操作。

symlink函数创建一个符号链接,函数声明如下:

[cpp] view plaincopy

  1. #include <unistd.h>
  2. int symlink(const char* actualpath, const char* sympath);

如果成功返回0,出错返回-1。

实践:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main(void){
  4. if(symlink("a","link2a") < 0){
  5. perror("symlink");
  6. return -1;
  7. }
  8. return 0;
  9. }

运行结果:

如果link2a不存在:

[email protected]:~/apue$ ll link2a
ls: cannot access link2a: No such file or directory
[email protected]:~/apue$ ./a.out
[email protected]:~/apue$ ll link2a a
-rw-rw-r-- 1 yan yan 0 Jul 10 10:04 a
lrwxrwxrwx 1 yan yan 1 Jul 10 10:06 link2a -> a

如果link2a已经存在:

lrwxrwxrwx 1 yan yan 1 Jul 10 10:06 link2a -> a
[email protected]:~/apue$ ./a.out
symlink: File exists

readlink函数读取符号链接本身,并读该链接中的名字,函数声明如下:

[cpp] view plaincopy

  1. #include <unistd.h>
  2. ssize_t readlink(const char* restrict pathname, char* restrict buf, size_t bufsize);

如果成功返回读到的字节,出错则返回-1.

实践:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main(void){
  4. char buf[256];
  5. if(readlink("symblicfile",buf,256)<0){
  6. perror("readlink");
  7. return -1;
  8. }
  9. printf("%s\n",buf);
  10. return 0;
  11. }

运行结果:

[email protected]:~/apue$ ll symblicfile
lrwxrwxrwx 1 yan yan 7 Jul 10 07:21 symblicfile -> desfile

[email protected]:~/apue$ ./a.out
desfile稾s

为什么会有乱码呢?原因是,buf中返回的字符串不会以null结尾,所以需要自己来添加:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. int main(void){
  5. char buf[256];
  6. memset(buf,0,256);
  7. if(readlink("symblicfile",buf,256)<0){
  8. perror("readlink");
  9. return -1;
  10. }
  11. buf[255] = 0;
  12. printf("%s\n",buf);
  13. return 0;
  14. }

运行结果:

[email protected]:~/apue$ ./a.out
desfile

时间: 2024-11-13 08:05:14

硬链接和符号链接的相关文章

UNIX环境编程学习笔记(10)——文件I/O之硬链接和符号链接

lienhua342014-09-15 1 文件系统数据结构 UNIX 文件系统通过 i 节点来存储文件的信息.如图 1 所示为一个磁盘柱面上的 i 节点和数据块示意图.其中 i 节点是一个固定长度的记录项,它包含了有关文件的大部分信息.数据块用于存储文件的实际内容.每个文件的 i 节点会记录该文件的内容所占用的数据块信息. 图 1: i 节点和数据块 图 1 中还有一些信息需要进行说明: 1. 每个目录项只存储了文件的文件名和 i 节点编号(每个文件系统各自对它们的 i 节点进行编号).文件的

硬链接与符号链接的比较?

今天就说说硬链接(实体链接)与符号链接(类似Windows的快捷方式)的不同? 首先我们应知道: 每个档案都会占用一个inode ,档案内容由 inode记录来指向; 想要读取该档案,必须要经过目录记录的文件名来指向正确的inode号才能通过block读取数据. 硬链接:只是在目录下新增一笔档名链接到某inode号码的关联记录而已,不占用空间大小. 重点:hard link 只是在某个目录下的block多写入一个关联数据而已,既不会增加inode也不会减少block. 借用鸟哥书中的例子来说,假

Linux上创建和更改硬链接和符号链接

概述 在本篇中,学习创建和管理硬链接和符号链接.学习: 创建硬或软链接 识别链接并知道它们的类型 理解复制与链接文件之间的区别 使用链接执行系统管理任务 链接简介 在存储设备上,文件或目录包含在一些数据块中.有关某个文件的信息包含在一个 inode 中,它记录了所有者.最后访问该文件的时间.文件的大小.它是否是目录,以及谁可以读取或写入它等信息.inode 编号也称为文件序列号 ,该编号在特定文件系统内是唯一的.一个 目录条目 包含一个文件或目录的名称,以及用来存储该文件或目录的信息的 inod

linux笔记-硬链接和符号链接

硬链接:指多个路径名(不同目录下的不同文件名)指向同一个硬盘数据,用其中的随便哪个文件打开修改数据,都会在其他文件打开中更新, 原因就是硬链接和“原”文件inode相同,每增加或者删除一个链接,链接计数加1或减1,当链接计数为0时,就在硬盘上删除遮盖inode即删除数据. 因为硬链接包含inode等信息,所以不能跨文件系统使用. 软链接(符号链接):每个软链接都有自己的inode并且保存被链接文件完整的路径名和数据块,所以可以跨系统链接,并且删除软链接对原文件并没有什么影响,但通过 软链接打开原

linux命令:ln 链接文件--硬链接,符号链接(软链接)

   ln命令简介: 默认创建硬链接,当使用-s 时创建符号链接. 1.命令格式:   ln [option] 原文件 链接文件   文件路径最好都用绝对路径   ln 原文件 链接文件   不带参数表示创建硬件链接     -s表示创建软链接    option(选项): -s  创建软链接 -v  显示创建过程. 硬链接:        1.只能对文件创建,不能应用于目录:        2.不能跨文件系统:        3.创建硬链接会增加文件被链接的次数:       符号链接(软链接

linux-磁盘,扇面,柱面,文件系统,硬链接,符号链接,du,df

磁盘.扇面.柱面 http://blog.chinaunix.net/uid-13245160-id-84370.html http://blog.chinaunix.net/uid-17246314-id-5676479.html 低级格式化:低级格式化就是将磁盘内容重新清空,恢复出厂时的状态,划分出的柱面和磁道,再将磁道划分为若干个扇区,每个扇区又划分出标识部分ID.间隔区GAP和数据区DATA等. 分区:文件系统 MBR:bootloader(446字节).分区表(64字节,4个分区).结

硬链接和软连接(符号链接)

硬链接:不同路径的文件指定的是同一个inode硬链接不能跨分区存在硬链接不能链接到目录(要避免循环引用)删除硬链接只会减少文件被硬链接的次数,源文件不会动.软链接:是一个独立的文件,有自己独立的inode,引用的是路径本身,不是inode删除软链接,跟源文件没任何关系软链接没有存储任何数据,只是存储了访问文件的另一种路径.软链接可以对目录创建,也可以跨分区源文件被删除,软连接将不可用.如果有什么不懂的话可以去看看<Linux就该这么学>这本书,非常适合新手学习Linux. 在实际应用中硬链接和

硬链接与软连接

写在前面 Linux系统中存在两种链接文件,硬链接(hard link)和符号链接(symbolic link).符号链接也称为软连接.想了解清楚这两种链接文件的区别并不容易,首先要清楚Linux文件系统的相关知识. 我们知道文件有文件名和数据.而Linux的文件系统在存储文件时分为两个部分,用户数据(userdata)和元数据(metadata).用户数据是文件的真实数据存储文件系统的data block中,元数据存储在一个iNode的节点块中,包括文件的iNode号,权限,大小,时间属性(a

linux软链接与硬链接的区别

Linux 文件系统最重要的特点之一是它的文件链接.链接是对文件的引用,这样可以让文件在文件系统中多处被看到.不过,在 Linux 中,链接可以如同原始文件一样来对待.链接可以与普通的文件一样被执行.编辑和访问.对系统中的其他应用程序而言,链接就是它所对应的原始文件.当您通过链接对文件进行编辑时,您编辑的实际上是原始文件.链接不是副本,linux有两种类型的链接:硬链接和符号链接(软链接). 硬链接(hard link)只能引用同一文件系统中的文件.它引用的是文件在文件系统中的物理索引(也称为