在学习有关libpcap的内容时,参考了文件《Programmingwith pcap》(链接:http://www.tcpdump.org/pcap.html),其中刚开始就遇到了问题,程序如下:
#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
printf("Device: %s\n", dev);
return(0);
}
问题如下:
[zhaihf@localhostpcap]$ ls
lookup_dev lookup_dev.c
[zhaihf@localhostpcap]$ gcc -g -o lookup_dev -lpcap lookup_dev.c-L/usr/local/lib
[zhaihf@localhost pcap]$./lookup_dev
./lookup_dev: errorwhile loading shared libraries: libpcap.so.1: cannot open sharedobject file: No such file or directory
[zhaihf@localhostpcap]$ ldd lookup_dev
linux-vdso.so.1 => (0x00007fff66eea000)
libpcap.so.1 => notfound
libc.so.6=> /lib64/libc.so.6 (0x00000037e2800000)
/lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)
[zhaihf@localhostpcap]$
2.1原因分析
原因1:共享库不存在或安装错误。
用rpm-qa | grep -i libpcap命令检查是否安装了libpcap和libpcap-devel。
[zhaihf@localhostpcap]$rpm -qa | grep -ilibpcap
libpcap-0.9.4-15.el5
原因2:共享库已经正确安装,但程序按照默认共享库路径找不到该共享库文件。
加载共享库因路径出错,肯定与ld有关,查看连接器ld的内容。
连接器使用下面的搜索路径来定位需要的共享库:
1.所有由'-rpath-link'选项指定的搜索路径.
2.所有由'-rpath'指定的搜索路径.'-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径被包含在可执行文件中,并在运行时使用,而'-rpath-link'选项仅仅在连接时起作用.它只用于本地连接器.
3.在一个ELF系统中,如果'-rpath'和'rpath-link'选项没有被使用,会搜索环境变量'LD_RUN_PATH'的内容.它也只对本地连接器起作用.
4.在SunOS上,'-rpath'选项不使用,只搜索所有由'-L'指定的目录.
5.对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索.
6.对于一个本地ELF连接器,共享库中的`DT_RUNPATH'和`DT_RPATH'操作符会被需要它的共享库搜索.如果'DT_RUNPATH'存在了,那'DT_RPATH'就会被忽略.
7.缺省目录,常规的,如'/lib'和'/usr/lib'.
8.对于ELF系统上的本地连接器,如果文件'/etc/ld.so.conf'存在,这个文件中有的目录会被搜索.
如果需要的共享库没有被找到,那连接器会发出一条警告信息,并继续执行连接.
共享库路径设置问题,如下:
1)如果共享库文件安装到了/lib或/usr/lib目录下,那么需执行一下ldconfig命令
ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.
2)如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下,那么在执行ldconfig命令前,还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中,如下:
[zhaihf@localhostpcap]$ cat /etc/ld.so.conf
includeld.so.conf.d/*.conf
[zhaihf@localhostpcap]$echo "/usr/local/lib" >> /etc/ld.so.conf
3)如果共享库文件安装到了其它"非/lib或/usr/lib"目录下, 但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径).那可以export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找共享库.
LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库.可以设置多个搜索目录,这些目录之间用冒号分隔开.比如安装了一个mysql到/usr/local/mysql目录下,其中有一大堆库文件在/usr/local/mysql/lib下面,则可以在.bashrc或.bash_profile或shell里加入以下语句即可:
exportLD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH
一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用.
4)如果程序需要的库文件比系统目前存在的文件版本低,可以做一个链接
比如:
errorwhile loading shared libraries: libncurses.so.4: cannot openshared
object file: No such file or directory
ls/usr/lib/libncu*
/usr/lib/libncurses.a /usr/lib/libncurses.so.5
/usr/lib/libncurses.so /usr/lib/libncurses.so.5.3
可见虽然没有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的
建一个链接就好了
[zhaihf@localhostpcap]$sudo ln -s /usr/local/lib/libpcap.so.1/usr/lib/libpcap.so.1
[zhaihf@localhostpcap]$whereis libpcap.so.1
libpcap.so:/usr/lib/libpcap.so.1 /usr/local/lib/libpcap.so.1/usr/local/lib/libpcap.so
[zhaihf@localhostpcap]$ ls -l /usr/lib/libpcap.so.1
lrwxrwxrwx 1 root root 27 Nov12 18:04 /usr/lib/libpcap.so.1 -> /usr/local/lib/libpcap.so.1
2.2正确结果
[zhaihf@localhostpcap]$ldd lookup_dev
linux-vdso.so.1 => (0x00007fff499ff000)
libpcap.so.1 =>/usr/local/lib/libpcap.so.1 (0x00007fd8d3292000)
libc.so.6 => /lib64/libc.so.6 (0x00000037e2800000)
/lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)
[zhaihf@localhostpcap]$ sudo ldd lookup_dev
linux-vdso.so.1 => (0x00007fff223ff000)
libpcap.so.1 => /usr/local/lib/libpcap.so.1(0x00007f7e6671b000)
libc.so.6 => /lib64/libc.so.6 (0x00000037e2800000)
/lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)
[zhaihf@localhostpcap]$ readelf -d lookup_dev
Dynamic sectionat offset 0x900 contains 21 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library:[libpcap.so.1]
0x0000000000000001(NEEDED) Shared library:[libc.so.6]
0x000000000000000c (INIT) 0x400520
0x000000000000000d (FINI) 0x4007c8
0x000000006ffffef5 (GNU_HASH) 0x400240
0x0000000000000005 (STRTAB) 0x4003b8
0x0000000000000006 (SYMTAB) 0x400280
0x000000000000000a (STRSZ) 155 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x600aa8
0x0000000000000002 (PLTRELSZ) 96 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x4004c0
0x0000000000000007 (RELA) 0x400490
0x0000000000000008 (RELASZ) 48 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x400470
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x400454
0x0000000000000000 (NULL) 0x0
[zhaihf@localhost pcap]$
3.1LD_LIBRARY_PATH
把动态链接库的安装路径(如/usr/local/lib)放到变量LD_LIBRARY_PATH里。
用命令export:
export LD_LIBRARY_PATH=/usr/local/lib
这只是临时设置变量LD_LIBRARY_PATH,下次开机,设置将不复存在;可以在~/.bashrc或者~/.bash_profile中加入export语句,
前者在每次登陆和每次打开shell都读取一次,
后者只在登陆时读取一次。
可采用如下语句来使设置生效:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
修改完后,记得关掉当前终端并重新打开一个新的终端,从而使上面的配置生效。
3.2 ld.so.conf
链接器ld默认的目录是/lib和/usr/lib,如果放在其他路径也可以,需要让ld知道库文件在哪里。
1>编辑/etc/ld.so.conf文件,在新的一行中加入库文件所在目录;
运行ldconfig,以更新/etc/ld.so.cache文件;
2>在/etc/ld.so.conf.d/目录下新建任何以.conf为后缀的文件,在该文件中加入库文件所在的目录;
运行ldconfig,以更新/etc/ld.so.cache文件;
第二种办法更为方便,对于原系统的改动最小。因为/etc/ld.so.conf文件的内容是include/etc/ld.so.conf.d/*.conf,所以,在/etc/ld.so.conf.d/目录下加入的任何以.conf为后缀的文件都能被识别到。
[zhaihf@localhostpcap]$ ls /etc/ld.so.conf.d/
gmp.conf mpc.conf mpfr.conf qt-x86_64.conf
[zhaihf@localhost pcap]$ ls/etc/ld.so.conf.d/
gmp.conf mpc.conf mpfr.conf pcap.conf qt-x86_64.conf
[zhaihf@localhost pcap]$ cat/etc/ld.so.conf.d/pcap.conf
/usr/local/lib/
[zhaihf@localhostpcap]$
ld.so.cache的更新是递增式的,就像PATH系统环境变量一样,不是从头重新建立,而是向上累加。
除非重新开机,才是从零开始建立ld.so.cache文件。
3.3命令
NAME
/sbin/ldconfig - configure dynamic linker runtime bindings
SYNOPSIS
/sbin/ldconfig [ -nNvXV ] [ -f conf ] [ -C cache ] [ -r root ]directory ...
/sbin/ldconfig-l [ -v ] library ...
/sbin/ldconfig -p
DESCRIPTION
ldconfig creates the necessary links and cache tothe most recent shared libraries found inthedirectories
specified on thecommand line, in the file /etc/ld.so.conf, and in the trusted directories (/lib and
/usr/lib). The cache is used by the run-time linker, ld.so orld-linux.so. ldconfig checks the header and
filenames of the libraries it encounters when determining whichversions should have their links updated.
ldconfigwill attempt to deduce the type of ELF libs (ie. libc5 orlibc6/glibc) based on what C libs, if any,
the library was linked against. Therefore, when making dynamic libraries, it is wise toexplicitly link
against libc(use -lc).
Someexisting libs do not contain enough information to allow thededuction of their type. Therefore, the
/etc/ld.so.conf file format allows the specification of an expectedtype. This is only used for those ELF
libs which we can not work out. The format is "dirname=TYPE",where TYPE can be libc4, libc5, or libc6. (This
syntax also works on the command line.) Spaces are not allowed. Also see the -p option. ldconfigshould
normally be run by thesuperuser as it may require write permission on some root owneddirectories and files.
OPTIONS
-v Verbose mode. Print current versionnumber, the name of each directory as it is scanned, and anylinks
that are created. Overrides quiet mode.
-n Only process directories specified on the command line. Don’tprocess the trusted directories (/lib
and /usr/lib) nor those specified in /etc/ld.so.conf. Implies-N.
-N Don’t rebuild the cache. Unless -X is also specified, linksare still updated.
-X Don’t update links. Unless -N is also specified, the cache isstill rebuilt.
-fconf
Use conf instead of /etc/ld.so.conf.
-Ccache
Use cache instead of /etc/ld.so.cache.
-rroot
Change to and use root as the root directory.
-l Library mode. Manually link individual libraries. Intended for use byexperts only.
-p Print the lists of directories and candidate libraries stored in thecurrent cache.
FILES
/lib/ld.so run-time linker/loader
/etc/ld.so.conf File containing a list of colon, space, tab, newline, or comma-separateddirectories in
which to search for libraries.
/etc/ld.so.cache File containing an ordered list of libraries found in the directories specified in
/etc/ld.so.conf.
NAME
ldd - print shared library dependencies
SYNOPSIS
ldd [OPTION]... FILE...
DESCRIPTION
ldd prints the shared libraries required byeach program or shared library specified on the command line.
OPTIONS
--version
Print the version number of ldd.
-v--verbose
Print all information, including e.g. symbol versioning information.
-u--unused
Print unused direct dependencies.
-d--data-relocs
Perform relocations and report any missing objects (ELFonly).
-r--function-relocs
Perform relocations for both data objects andfunctions, and report any missing objects or functions
(ELF only).
--helpUsage information.
NOTES
The standard version of ldd comes with glibc2. Libc5 came with anolder version, still present on some sys-
tems. The long options are not supported by the libc5 version. On the other hand, the glibc2 version does not
support -V and only has the equivalent --version.
Thelibc5 version of this program will use the name of a library given onthe command line as-is when it con-
tains a ’/’; otherwise it searches for the library in thestandard locations. To run it on a shared library in
the current directory, prefix the name with "./".
BUGS
ldd does not work on a.out shared libraries.
ldddoes not work with some extremely old a.out programs which were builtbefore ldd support was added to the
compiler releases. If you use ldd on one of these programs, theprogram will attempt to run with argc = 0 and
the results will be unpredictable.
SEE ALSO
ld.so(8), ldconfig(8)
NAME
ld.so, ld-linux.so* - dynamic linker/loader
DESCRIPTION
The programs ld.so and ld-linux.so* find and load the sharedlibraries
needed by aprogram, prepare the program to run, and then run it.
Linuxbinaries require dynamic linking (linking at run time) unlessthe
-static option was givento ld during compilation.
The program ld.so handles a.out binaries, a format used long ago;ld-
linux.so* handles ELF(/lib/ld-linux.so.1 for libc5, /lib/ld-linux.so.2
for glibc2), which everybody has been using for yearsnow. Otherwise
bothhave the same behaviour, and use the same support files and pro-
grams ldd(1),ldconfig(8) and /etc/ld.so.conf.
The shared libraries needed by the program are searched for invarious
places:
o (ELF only) Using the DT_RPATH dynamic section attribute of the
binary if present and DT_RUNPATH attribute does not exist. Use
of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH. Except if the
executable is a set-user-ID/set-group-ID binary, in whichcase
it is ignored.
o (ELF only) Using the DT_RUNPATH dynamic section attribute ofthe
binary if present.
o From the cache file /etc/ld.so.cache which contains acompiled
list of candidate libraries previously found in the augmented
library path. If, however, the binary was linked with -znode-
flib linker option, libraries in the default library paths are
skipped.
o In the default path /lib, and then /usr/lib. If thebinary was
linked with -z nodeflib linker option, this step is skipped.
SYNOPSIS
The dynamic linker can be run either indirectly through running some
dynamically linked program or library (in whichcase no command line
optionsto the dynamic linker can be passed and, in the ELF case, the
dynamic linker which isstored in the .interp section of the program is
executed) or directly by running:
/lib/ld-linux.so.* [OPTIONS] [PROGRAM [ARGUMENTS]]
COMMAND LINEOPTIONS
--list List alldependencies and how they are resolved.
--verify
Verify that program is dynamically linked and this dynamic
linker can handle it.
--library-pathPATH
Override LD_LIBRARY_PATH environment variable setting (see
below).
--ignore-rpathLIST
Ignore RPATH and RUNPATH information in object names in LIST.
This option has been supported by glibc2 forabout one hour.
Then it was renamed into:
--inhibit-rpathLIST
ENVIRONMENT
There are four important environment variables.
LD_LIBRARY_PATH
A colon-separated list of directories in which to search forELF
libraries at execution-time. Similar to thePATH environment
variable.
LD_PRELOAD
A whitespace-separated list of additional, user-specified, ELF
shared libraries to be loaded before all others. This can be
used to selectively override functions in other shared
libraries. For set-user-ID/set-group-ID ELF binaries, only
libraries in the standard search directories that are also set-
user-ID will be loaded.
LD_BIND_NOW
(libc5; glibc since 2.1.1) If set to non-emptystring, causes
the dynamic linker to resolve all symbols at program startup
instead of deferring function call resolval to thepoint when
they are first referenced. This is useful when using a debug-
ger.
LD_TRACE_LOADED_OBJECTS
(ELF only) If set to non-empty string, causesthe program to
list its dynamic library dependencies, as if run by ldd(1),
instead of running normally.
Thenthere are lots of more or less obscure variables, many obsoleteor
only for internal use.
LD_WARN
(ELF only)(glibc since 2.1.3) If set to non-empty string, warn
about unresolved symbols.
LD_NOWARN
(a.out only)(libc5) Suppress warnings about a.out librarieswith
incompatible minor version numbers.
LD_BIND_NOT
(glibc since 2.1.95) Do not update the GOT (global offsettable)
and PLT (procedure linkage table) after resolving a symbol.
LD_DEBUG
(glibc since 2.1) Output verbose debugging information aboutthe
dynamic linker. If set to all prints all debugging information
it has, if set to help prints a help message about whichcate-
gories can be specified in this environment variable.
LD_DEBUG_OUTPUT
(glibc since 2.1) File where LD_DEBUG output should be fedinto,
default is standard output. LD_DEBUG_OUTPUT is ignored forset-
user-ID/set-group-ID binaries.
LD_VERBOSE
(glibc since 2.1) If set to non-empty string, output symbolver-
sioning information about the program if queryinginformation
about the program (ie. either LD_TRACE_LOADED_OBJECTS has been
set, or --list or --verify options have been given to the
dynamic linker).
LD_PROFILE
(glibc since 2.1) Shared object to be profiled.
LD_PROFILE_OUTPUT
(glibc since 2.1) File where LD_PROFILE output should bestored,
default is standard output. LD_PROFILE_OUTPUTis ignored for
set-user-ID/set-group-ID binaries.
LD_AOUT_LIBRARY_PATH
(libc5) Version of LD_LIBRARY_PATH for a.out binaries only. Old
versions of ld-linux.so.1 also supported LD_ELF_LIBRARY_PATH.
LD_AOUT_PRELOAD
(libc5) Version of LD_PRELOAD for a.out binaries only. Oldver-
sions of ld-linux.so.1 also supported LD_ELF_PRELOAD.
LD_SHOW_AUXV
(glibc since 2.1) Show auxiliary array passed up from the ker-
nel.
LD_HWCAP_MASK
(glibc since 2.1) Mask for hardware capabilities.
LD_ORIGIN_PATH
(glibc since 2.1) Path where the binary is found (fornon-set-
user-ID programs).
LD_DYNAMIC_WEAK
(glibc since 2.1.91) Allow weak symbols to be overridden
(reverting to old glibc behaviour).
LD_KEEPDIR
(a.out only)(libc5) Don’t ignore the directory in thenames of
a.out libraries to be loaded. Use of this option is strongly
discouraged.
LDD_ARGV0
(libc5) argv[0] to be used by ldd(1) when none is present.
FILES
/lib/ld.so
a.out dynamic linker/loader
/lib/ld-linux.so.{1,2}
ELF dynamic linker/loader
/etc/ld.so.cache
File containing a compiled list of directories in which to
search for libraries and an ordered list of candidatelibraries.
/etc/ld.so.preload
File containing a whitespace separated list of ELF shared
libraries to be loaded before the program.
lib*.so*
shared libraries
NOTES
The ld.so functionality is available for executables compiled using
libc version 4.4.3 or greater. ELF functionality isavailable since
Linux 1.1.52and libc5.
SEE ALSO
ldd(1), ldconfig(8)