链接有两种,一种被称为硬链接(Hard Link),另一种被称为软链接或符号链接(Symbolic Link)。符号链接是一类特殊的文件, 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用。符号链接最早在4.2BSD版本中出现(1983年)。今天POSIX操作系统标准、大多数类Unix系统都支持符号链接。

 

一、Linux中Hard Link与Symbolic Link:基本概念

在Linux的文件系统中,一个文件对应一个inode与若干个data block。inode与data block都通过编号来标识,例如第917931个inode,第20112个data block。inode中记录着文件的属性,如文件的所有者、所属用户组、对文件的权限以及指向data block的指针。文件的真正内容是存放在data block中的。一个文件的内容,被分割成若干部分保存在不同的data block中,通过inode可以找到文件对应的所有data block。使用ls命令并打开-i选项就可以查看文件的inode编号:

*使用ls --help命令可以看到其中一行内容是:

-i, --inode                print the index number of each file

A hard link: a mapping from a file name to some file’s data。这种Link不会占用磁盘空间。例如,现在有一个名为JonathanFileHL的Hard Link指向JonathanFile.txt,实际上,JonathanFileHL和JonathanFile.txt具有相同的inode。如下面的示意图(图片来自【1】):

A soft/symbolic link: a mapping from a file name to another file name; whenever you refer to a symbolic link, the system will automatically translate it to the target name。Symbolic Link:这种Link会实际赞用磁盘空间。例如,现在有一个名为JonathanFileSL的Symbolic Link指向JonathanFile.txt,JonathanFileSL将会有独立的inode以及data block。源文件的文件名保存在Symbolic Link的。对源文件重命名或者删除,将会导致Symbolic Link失效。Symbolic Link的示意图如下:

创建Link的命令为ln,如果指定了-s选项,那么将会创建Symbolic Link,否则就是Hard Link。

首先创建文件original.txt,创建original.txt的硬连接 hard.txt(使用ln命令),并查看所有文件的属性。可以发现,original.txt和 hard.txt的属性完全一致(它们的inode完全一致,若两个文件,拥有同样的inode,那么就产生了所谓的硬连接。红框标出),注意其中蓝色圈标出的数字表示的就是该文件的硬连接数。这也告诉我们查看soft link的方法:

  1. Open a terminal and move to that directory.
  2. Type the command: ls -la. This shall long list all the files in the directory even if they are hidden.
  3. The files that start with l are your symbolic link files——最后一行中lrwxrwxrwx中第一个字母l就表示soft link,而且后面紫色圈中也示出了soft link的指向。

二、深入理解Hard Link与Symbolic Link

inode block: this is the formal name used to refer to “the first block of a file” in Linux; 

Hard link: another directory entry for a given file

上图中的link count记录了有多少个hard link指向这个文件。只有当所有的hard link都被删除后(即link count变为0),文件才真的被删除。

The inode of a symbolic file contains:

  • A flag saying that “I am symbolic link”
  • A file name of the target file

Soft Link存在的意义是什么呢?Very important for software upgrade——After upgrade, you just redirect the symbolic link to the new version.

三、/usr/bin/ld: cannot find -lxxx 错误

这是在Linux中编译程序的时候,可能会出现的一个错误。这个错误是因为链接程序ld在指定目录里找不到libxxx.so这个库。而且,你在使用gcc编译程序的时候一定使用了-l这个参数:它用来指定程序要链接的库,-l参数紧接着就是库名。这里的库名并非真正的库文件名。以库名为math的库为例,他的库文件名是libmath.so或者libmath.a(Linux下的库文件都要以lib开头,其中.so是动态库,.a是静态库)。可见,把库文件名的头lib和尾.so去掉就是库名了。
 
 
现在,如果我们要用到一个第三方提供的库libtest.so,那么只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,就能用上libtest.so库了。实际上,以下两个命令是等价的:
 
gcc -o mytest mytest.c /usr/lib/libtest.so
gcc -o mytest mytest.c -ltest

放在/lib/usr/lib/usr/local/lib里的库直接用-l参数就能链接了(如果是标准C语言库,可以不指定其库路径和库名称)。

如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:

/usr/bin/ld: cannot find -lxxx

也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest。

另外,其实大部分libxxxx.so只是一个soft link,比如libgfortran.so链接到/lib/x86_64-linux-gnu/libgfortran.so.4,libgfortran.so.4又链接到libgfortran.so.4.0.0,

如果没有这样的链接,则会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx库,而只有libxxxx.so.x或者libxxxx-x.x.x.so,就需要创造一个soft link。

 
总的来说,如果编译程序时遇到/usr/bin/ld: cannot find -lxxx,那么发生这种错误的原因有以下三种情形:
  1. 系统没有安装相对应的lib
  2. 相对应的lib版本不对
  3. lib(.so档)的symbolic link不正确,没有连结到正确的函式库文件(.so)
解决方法:
  1. 先判断在/usr/lib 下的相对应的函式库文件(.so) 的symbolic link 是否正确,若不正确改成正确的连结目标即可解决问题。
  2. 若不是symbolic link 的问题引起,而是系统缺少相对应的lib,那么安装lib即可解决。

 

 
【本文完】

参考文献与推荐阅读材料

【1】Hard Link与Symbolic Link

【2】gcc的-l参数和-L参数

 

 

GitHub 加速计划 / li / linux-dash
10
2
下载
A beautiful web dashboard for Linux
最近提交(Master分支:19 天前 )
186a802e added ecosystem file for PM2 5 年前
5def40a3 Add host customization support for the NodeJS version 5 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐