php

php命令是流行的Web开发语言PHP的命令行接口,可以使用PHP语言开发基于命令行的系统管理脚本程序。

语法

php(选项)(参数)

选项

-a:进入交互模式;
-c:指定“php.ini”的搜索路径。

参数

文件:要执行的php脚本。

test

test命令是shell环境中测试条件表达式的实用工具。

语法

test(选项)

选项

-b<文件>:如果文件为一个块特殊文件,则为真;
-c<文件>:如果文件为一个字符特殊文件,则为真;
-d<文件>:如果文件为一个目录,则为真;
-e<文件>:如果文件存在,则为真;
-f<文件>:如果文件为一个普通文件,则为真;
-g<文件>:如果设置了文件的SGID位,则为真;
-G<文件>:如果文件存在且归该组所有,则为真;
-k<文件>:如果设置了文件的粘着位,则为真;
-O<文件>:如果文件存在并且归该用户所有,则为真;
-p<文件>:如果文件为一个命名管道,则为真;
-r<文件>:如果文件可读,则为真;
-s<文件>:如果文件的长度不为零,则为真;
-S<文件>:如果文件为一个套接字特殊文件,则为真;
-u<文件>:如果设置了文件的SUID位,则为真;
-w<文件>:如果文件可写,则为真;
-x<文件>:如果文件可执行,则为真。

实例

linux中shell编程中的test常见用法:

判断表达式

if test     #表达式为真
if test !   #表达式为假
test 表达式1 –a 表达式2     #两个表达式都为真
test 表达式1 –o 表达式2     #两个表达式有一个为真
test 表达式1 ! 表达式2       #条件求反

判断字符串

test –n 字符串    #字符串的长度非零
test –z 字符串    #字符串的长度是否为零
test 字符串1=字符串2       #字符串是否相等,若相等返回true
test 字符串1!=字符串2      #字符串是否不等,若不等反悔false

判断整数

test 整数1 -eq 整数2    #整数相等
test 整数1 -ge 整数2    #整数1大于等于整数2
test 整数1 -gt 整数2    #整数1大于整数2
test 整数1 -le 整数2    #整数1小于等于整数2
test 整数1 -lt 整数2    #整数1小于整数2
test 整数1 -ne 整数2    #整数1不等于整数2

判断文件

test File1 –ef File2    两个文件是否为同一个文件,可用于硬连接。主要判断两个文件是否指向同一个inode。
test File1 –nt File2    判断文件1是否比文件2新
test File1 –ot File2    判断文件1比是否文件2旧
test –b file   #文件是否块设备文件
test –c File   #文件并且是字符设备文件
test –d File   #文件并且是目录
test –e File   #文件是否存在 (常用)
test –f File   #文件是否为正规文件 (常用)
test –g File   #文件是否是设置了组id
test –G File   #文件属于的有效组ID
test –h File   #文件是否是一个符号链接(同-L)
test –k File   #文件是否设置了Sticky bit位
test –b File   #文件存在并且是块设备文件
test –L File   #文件是否是一个符号链接(同-h)
test –o File   #文件的属于有效用户ID
test –p File   #文件是一个命名管道
test –r File   #文件是否可读
test –s File   #文件是否是非空白文件
test –t FD     #文件描述符是在一个终端打开的
test –u File   #文件存在并且设置了它的set-user-id位
test –w File   #文件是否存在并可写
test –x File   #文件属否存在并可执行

expr

expr命令是一款表达式计算工具,使用它完成表达式的求值操作。

expr的常用运算符:

  • 加法运算:+
  • 减法运算:-
  • 乘法运算:\*
  • 除法运算:/
  • 求摸(取余)运算:%

语法

expr(选项)(参数)

选项

--help:显示指令的帮助信息;
--version:显示指令版本信息。

参数

表达式:要求值的表达式。

实例

result=`expr 2 + 3`
result=$(expr $no1 + 5)

gcc

gcc命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点。现在很多程序员都应用GCC,怎样才能更好的应用GCC。目前,GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序,可根据需要选择安装支持的语言。

语法

gcc(选项)(参数)

选项

-o:指定生成的输出文件;
-E:仅执行编译预处理;
-S:将C代码转换为汇编代码;
-wall:显示警告信息;
-c:仅执行编译操作,不进行连接操作。

参数

C源文件:指定C语言源代码文件。

实例

常用编译命令选项

假设源程序文件名为test.c

无选项编译链接

gcc test.c

将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。

选项 -o

gcc test.c -o test

将test.c预处理、汇编、编译并链接形成可执行文件test。-o选项用来指定输出文件的文件名。

选项 -E

gcc -E test.c -o test.i

将test.c预处理输出test.i文件。

选项 -S

gcc -S test.i

将预处理输出文件test.i汇编成test.s文件。

选项 -c

gcc -c test.s

将汇编输出文件test.s编译输出test.o文件。

无选项链接

gcc test.o -o test

将编译输出文件test.o链接成最终可执行文件test。

选项 -O

gcc -O1 test.c -o test

使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长。

多源文件的编译方法

如果有多个源文件,基本上有两种编译方法:

假设有两个源文件为test.c和testfun.c

多个文件一起编译

gcc testfun.c test.c -o test

将testfun.c和test.c分别编译后链接成test可执行文件。

分别编译各个源文件,之后对编译后输出的目标文件链接。

gcc -c testfun.c    #将testfun.c编译成testfun.o
gcc -c test.c       #将test.c编译成test.o
gcc -o testfun.o test.o -o test    #将testfun.o和test.o链接成test

以上两种方法相比较,第一中方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译。

gdb

gdb命令包含在GNU的gcc开发套件中,是功能强大的程序调试器。GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调试工作。

命令 解释 示例
file <文件名> 加载被调试的可执行程序文件。
因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径。
(gdb) file gdb-sample
r Run的简写,运行被调试的程序。
如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。
(gdb) r
c Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。 (gdb) c
b <行号>
b <函数名称>
b *<函数名称>
b *<代码地址> d [编号]
b: Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。
其中在函数名称前面加“*”符号表示将断点设置在“由编译器生成的prolog代码处”。如果不了解汇编,可以不予理会此用法。 d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。
(gdb) b 8
(gdb) b main
(gdb) b *main
(gdb) b *0x804835c (gdb) d
s, n s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;
n: 执行一行源程序代码,此行代码中的函数调用也一并执行。 s 相当于其它调试器中的“Step Into (单步跟踪进入)”;
n 相当于其它调试器中的“Step Over (单步跟踪)”。 这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。
(gdb) s
(gdb) n
si, ni si命令类似于s命令,ni命令类似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源代码。 (gdb) si
(gdb) ni
p <变量名称> Print的简写,显示指定变量(临时变量或全局变量)的值。 (gdb) p i
(gdb) p nGlobalVar
display … undisplay <编号> display,设置程序中断后欲显示的数据及其格式。
例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令
“display /i $pc”
其中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。 undispaly,取消先前的display设置,编号从1开始递增。
(gdb) display /i $pc (gdb) undisplay 1
i info的简写,用于显示各类信息,详情请查阅“help i”。 (gdb) i r
q Quit的简写,退出GDB调试环境。 (gdb) q
help [命令名称] GDB帮助命令,提供对GDB名种命令的解释说明。
如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。
(gdb) help

语法

gdb(选项)(参数)

选项

-cd:设置工作目录;
-q:安静模式,不打印介绍信息和版本信息;
-d:添加文件查找路径;
-x:从指定文件中执行GDB指令;
-s:设置读取的符号表文件。

参数

文件:二进制可执行程序。

实例

以下是linux下dgb调试的一个实例,先给出一个示例用的小程序,C语言代码:

#include <stdio.h>
int nGlobalVar = 0;

int tempFunction(int a, int b)
{
    printf("tempFunction is called, a = %d, b = %d /n", a, b);
    return (a + b);
}

int main()
{
    int n;
        n = 1;
        n++;
        n--;

        nGlobalVar += 100;
        nGlobalVar -= 12;

    printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);

        n = tempFunction(1, 2);
    printf("n = %d", n);

    return 0;
}

请将此代码复制出来并保存到文件 gdb-sample.c 中,然后切换到此文件所在目录,用GCC编译之:

gcc gdb-sample.c -o gdb-sample -g

在上面的命令行中,使用 -o 参数指定了编译生成的可执行文件名为 gdb-sample,使用参数 -g 表示将源代码信息编译到可执行文件中。如果不使用参数 -g,会给后面的GDB调试造成不便。当然,如果我们没有程序的源代码,自然也无从使用 -g 参数,调试/跟踪时也只能是汇编代码级别的调试/跟踪。

下面“gdb”命令启动GDB,将首先显示GDB说明,不管它:

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
(gdb)

上面最后一行“(gdb)”为GDB内部命令引导符,等待用户输入GDB命令。

下面使用“file”命令载入被调试程序 gdb-sample(这里的 gdb-sample 即前面 GCC 编译输出的可执行文件):

(gdb) file gdb-sample
Reading symbols from gdb-sample...done.

上面最后一行提示已经加载成功。

下面使用“r”命令执行(Run)被调试文件,因为尚未设置任何断点,将直接执行到程序结束:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

下面使用“b”命令在 main 函数开头设置一个断点(Breakpoint):

(gdb) b main
Breakpoint 1 at 0x804835c: file gdb-sample.c, line 19.

上面最后一行提示已经成功设置断点,并给出了该断点信息:在源文件 gdb-sample.c 第19行处设置断点;这是本程序的第一个断点(序号为1);断点处的代码地址为 0x804835c(此值可能仅在本次调试过程中有效)。回过头去看源代码,第19行中的代码为“n = 1”,恰好是 main 函数中的第一个可执行语句(前面的“int n;”为变量定义语句,并非可执行语句)。

再次使用“r”命令执行(Run)被调试程序:

(gdb) r
Starting program: /home/liigo/temp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;

程序中断在gdb-sample.c第19行处,即main函数是第一个可执行语句处。

上面最后一行信息为:下一条将要执行的源代码为“n = 1;”,它是源代码文件gdb-sample.c中的第19行。

下面使用“s”命令(Step)执行下一行代码(即第19行“n = 1;”):

(gdb) s
20 n++;

上面的信息表示已经执行完“n = 1;”,并显示下一条要执行的代码为第20行的“n++;”。

既然已经执行了“n = 1;”,即给变量 n 赋值为 1,那我们用“p”命令(Print)看一下变量 n 的值是不是 1 :

(gdb) p n
$1 = 1

果然是 1。($1大致是表示这是第一次使用“p”命令——再次执行“p n”将显示“$2 = 1”——此信息应该没有什么用处。)

下面我们分别在第26行、tempFunction 函数开头各设置一个断点(分别使用命令“b 26”“b tempFunction”):

(gdb) b 26
Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.
(gdb) b tempFunction
Breakpoint 3 at 0x804832e: file gdb-sample.c, line 12.

使用“c”命令继续(Continue)执行被调试程序,程序将中断在第二 个断点(26行),此时全局变量 nGlobalVar 的值应该是 88;再一次执行“c”命令,程序将中断于第三个断点(12行,tempFunction 函数开头处),此时tempFunction 函数的两个参数 a、b 的值应分别是 1 和 2:

(gdb) c
Continuing.

Breakpoint 2, main () at gdb-sample.c:26
26 printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
(gdb) p nGlobalVar
$2 = 88
(gdb) c
Continuing.
n = 1, nGlobalVar = 88

Breakpoint 3, tempFunction (a=1, b=2) at gdb-sample.c:12
12 printf("tempFunction is called, a = %d, b = %d /n", a, b);
(gdb) p a
$3 = 1
(gdb) p b
$4 = 2

上面反馈的信息一切都在我们预料之中~~

再一次执行“c”命令(Continue),因为后面再也没有其它断点,程序将一直执行到结束:

(gdb) c
Continuing.
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

有时候需要看到编译器生成的汇编代码,以进行汇编级的调试或跟踪,又该如何操作呢?

这就要用到display命令“display /i $pc”了(此命令前面已有详细解释):

(gdb) display /i $pc
(gdb)

此后程序再中断时,就可以显示出汇编代码了:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

看到了汇编代码,“n = 1;”对应的汇编代码是“movl $0x1,0xfffffffc(%ebp)”。

并且以后程序每次中断都将显示下一条汇编指定(“si”命令用于执行一条汇编代码——区别于“s”执行一行C代码):

(gdb) si
20 n++;
1: x/i $pc 0x8048363 <main+23>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x08048366 20 n++;
1: x/i $pc 0x8048366 <main+26>: incl (%eax)
(gdb) si
21 n--;
1: x/i $pc 0x8048368 <main+28>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x0804836b 21 n--;
1: x/i $pc 0x804836b <main+31>: decl (%eax)
(gdb) si
23 nGlobalVar += 100;
1: x/i $pc 0x804836d <main+33>: addl $0x64,0x80494fc

接下来我们试一下命令“b *<函数名称>”。

为了更简明,有必要先删除目前所有断点(使用“d”命令——Delete breakpoint):

(gdb) d
Delete all breakpoints? (y or n) y
(gdb)

当被询问是否删除所有断点时,输入“y”并按回车键即可。

下面使用命令“b *main”在 main 函数的 prolog 代码处设置断点(prolog、epilog,分别表示编译器在每个函数的开头和结尾自行插入的代码):

(gdb) b *main
Breakpoint 4 at 0x804834c: file gdb-sample.c, line 17.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 4, main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834c <main>: push %ebp
(gdb) si
0x0804834d 17 {
1: x/i $pc 0x804834d <main+1>: mov %esp,%ebp
(gdb) si
0x0804834f in main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834f <main+3>: sub $0x8,%esp
(gdb) si
0x08048352 17 {
1: x/i $pc 0x8048352 <main+6>: and $0xfffffff0,%esp
(gdb) si
0x08048355 17 {
1: x/i $pc 0x8048355 <main+9>: mov $0x0,%eax
(gdb) si
0x0804835a 17 {
1: x/i $pc 0x804835a <main+14>: sub %eax,%esp
(gdb) si
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

此时可以使用“i r”命令显示寄存器中的当前值———“i r”即“Infomation Register”:

(gdb) i r
eax 0xbffff6a4 -1073744220
ecx 0x42015554 1107383636
edx 0x40016bc8 1073834952
ebx 0x42130a14 1108544020
esp 0xbffff6a0 0xbffff6a0
ebp 0xbffff6a8 0xbffff6a8
esi 0x40015360 1073828704
edi 0x80483f0 134513648
eip 0x8048366 0x8048366
eflags 0x386 902
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x33 51

当然也可以显示任意一个指定的寄存器值:

(gdb) i r eax
eax 0xbffff6a4 -1073744220

最后一个要介绍的命令是“q”,退出(Quit)GDB调试环境:

(gdb) q
The program is running. exit anyway? (y or n)

indent

indent命令可辨识C的原始代码文件,并加以格式化,以方便程序员阅读、修改等操作。

语法

indent(选项)(源文件)
或
indent(选项)(源文件)(-o 目标文件)

选项

-bad:在声明区加上空白行;
-bap:添加空白行;
-bbb:在注释后面添加空白行;
-bc:在声明段中,如果出现逗号就换行;
-bl:if(或是else、for等)与后面执行区段的“{”不同行,且“}”自成一行-bli<缩排格数>设置{}缩排的格数;
-br:if(或是else、for等)与后面执行区段的“{”同行,且“}”自成一行;
-bs:在sizeof之后空一格;
-c<栏数>:将注释置于程序右侧指定的栏位;
-cd<栏数>:将注释置于声明右侧指定的栏位;
-cdb:注释符号自成一行;
-ce:将else置于“}”(if执行区段的结尾)之后;
-ci:<缩排格数>:叙述过长而换行时,指定换行后缩排的格数;
-cli<缩排格数>:使用case时,switch缩排的格数;
-cp<栏数>:将注释置于else与elseif叙述右侧指定的栏位;
-cs:在case之后空一格;
-d<缩排格数>:针对不是放在程序码右侧的注释,设置其缩排格数;
-di<栏数>:将声明区段的变量置于指定的栏位;
-fc1:针对放在每行最前端的注释,设置其格式;
-fca:设置所有注释的格式;
-gnu:使用指定的GNU格式,该参数为默认值;
-i<格数>:设置缩排的格数;
-ip<格数>:设置参数的缩排格数;
-kr:指定使用Kernighan&Ritchie的格式;
-lp:叙述过长而换行,且叙述中包含了括号时,将括号中的每行起始栏位内容垂直对其排列;
-nbad:在声明区段后不要加上空白行;
-nbap:在程序后面不添加空白行;
-nbbb:在注释段后面不添加空白行;
-nbc:在声明段中,即使出现逗号,也不换行;
-ncdb:注释符号不自成一行;
-nce:不将else置于“}”后面;
-ncs:不在case后面空一格;
-nfc1:不要格式化放在每行最前端的注释;
-nfca:不用格式化任何的注释;
-nip:参数不要缩排;
-nlp:叙述过长而换行,且叙述中包含了括号时,不用将括号中的每行起始栏位垂直对其排列;
-npcs:在调用函数名之后,不要添加空格;
-npro:不要读取indent的配置文件“.indent.pro”;
-npsl:程序类型与程序名称放在同一行;
-nsc:注释左侧不要添加星号;
-nsob:不用处理多余的空白行;
-nss:若for或while区段仅有一行时,在分号前不加空格;
-nv:不显示详细的信息;
-orig:使用berkeley格式;
-pcs:在调用函数名与“{”之间添加空格;
-psl:程序类型置于程序名称的前一行;
-sc:在每行注释左侧添加星号;
-sob:删除多余的空白行;
-ss:若for或swile区段仅有一行时,在分号前加上空格;
-st:将结果显示在标准输出设备上;
-T:数据类型名称缩排;
-ts<格数>:设置tab的长度;
-v:显示详细的执行过程;
--version:显示版本信息。

实例

使用indent命令将C语言源文件"test.c"中所有的sizeof后面添加一个空格,输入如下命令:

indent -bs /home/rootlocal/桌面/test.c

执行上面的命令后,用户可以打开指定的源文件查看在sizeof后面是否都添加了一个空格。由于该命令的参数非常多,所以用户可以根据实际需要选择适合的参数进行使用即可。

pstack

pstack命令可显示每个进程的栈跟踪。pstack 命令必须由相应进程的属主或 root 运行。可以使用 pstack 来确定进程挂起的位置。此命令允许使用的唯一选项是要检查的进程的 PID

命令软件包下载地址:https://packages.debian.org/sid/pstack

实例

pstree以树结构显示进程

pstree -p work | grep ad
sshd(22669)---bash(22670)---ad_preprocess(4551)-+-{ad_preprocess}(4552)
                                                |-{ad_preprocess}(4553)
                                                |-{ad_preprocess}(4554)
                                                |-{ad_preprocess}(4555)
                                                |-{ad_preprocess}(4556)
                                                `-{ad_preprocess}(4557)

work为工作用户,-p为显示进程识别码,ad_preprocess共启动了6个子线程,加上主线程共7个线程。

ps -Lf 4551
UID        PID  PPID   LWP  C NLWP STIME TTY      stat   time CMD
work      4551 22670  4551  2    7 16:30 pts/2    Sl+    0:02 ./ad_preprocess
work      4551 22670  4552  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess
work      4551 22670  4553  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess
work      4551 22670  4554  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess
work      4551 22670  4555  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess
work      4551 22670  4556  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess
work      4551 22670  4557  0    7 16:30 pts/2    Sl+    0:00 ./ad_preprocess

进程共启动了7个线程

pstack显示每个进程的栈跟踪:

pstack 4551
Thread 7 (Thread 1084229984 (LWP 4552)):
#0  0x000000302afc63dc in epoll_wait () from /lib64/tls/libc.so.6
#1  0x00000000006f0730 in ub::EPollEx::poll ()
#2  0x00000000006f172a in ub::NetReactor::callback ()
#3  0x00000000006fbbbb in ub::UBTask::CALLBACK ()
#4  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6  0x0000000000000000 in ?? ()
Thread 6 (Thread 1094719840 (LWP 4553)):
#0  0x000000302afc63dc in epoll_wait () from /lib64/tls/libc.so.6
#1  0x00000000006f0730 in ub::EPollEx::poll ()
#2  0x00000000006f172a in ub::NetReactor::callback ()
#3  0x00000000006fbbbb in ub::UBTask::CALLBACK ()
#4  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6  0x0000000000000000 in ?? ()
Thread 5 (Thread 1105209696 (LWP 4554)):
#0  0x000000302b80baa5 in __nanosleep_nocancel ()
#1  0x000000000079e758 in comcm::ms_sleep ()
#2  0x00000000006c8581 in ub::UbClientManager::healthyCheck ()
#3  0x00000000006c8471 in ub::UbClientManager::start_healthy_check ()
#4  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6  0x0000000000000000 in ?? ()
Thread 4 (Thread 1115699552 (LWP 4555)):
#0  0x000000302b80baa5 in __nanosleep_nocancel ()
#1  0x0000000000482b0e in armor::armor_check_thread ()
#2  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#3  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#4  0x0000000000000000 in ?? ()
Thread 3 (Thread 1126189408 (LWP 4556)):
#0  0x000000302af8f1a5 in __nanosleep_nocancel () from /lib64/tls/libc.so.6
#1  0x000000302af8f010 in sleep () from /lib64/tls/libc.so.6
#2  0x000000000044c972 in Business_config_manager::run ()
#3  0x0000000000457b83 in Thread::run_thread ()
#4  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6  0x0000000000000000 in ?? ()
Thread 2 (Thread 1136679264 (LWP 4557)):
#0  0x000000302af8f1a5 in __nanosleep_nocancel () from /lib64/tls/libc.so.6
#1  0x000000302af8f010 in sleep () from /lib64/tls/libc.so.6
#2  0x00000000004524bb in Process_thread::sleep_period ()
#3  0x0000000000452641 in Process_thread::run ()
#4  0x0000000000457b83 in Thread::run_thread ()
#5  0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#6  0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#7  0x0000000000000000 in ?? ()
Thread 1 (Thread 182894129792 (LWP 4551)):
#0  0x000000302af8f1a5 in __nanosleep_nocancel () from /lib64/tls/libc.so.6
#1  0x000000302af8f010 in sleep () from /lib64/tls/libc.so.6
#2  0x0000000000420d79 in Ad_preprocess::run ()
#3  0x0000000000450ad0 in main ()

objdump

objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具。

选项

--archive-headers 
-a 
显示档案库的成员信息,类似ls -l将lib*.a的信息列出。 

-b bfdname 
--target=bfdname 
指定目标码格式。这不是必须的,objdump能自动识别许多格式,比如: 

objdump -b oasys -m vax -h fu.o 
显示fu.o的头部摘要信息,明确指出该文件是Vax系统下用Oasys编译器生成的目标文件。objdump -i将给出这里可以指定的目标码格式列表。 

-C 
--demangle 
将底层的符号名解码成用户级名字,除了去掉所开头的下划线之外,还使得C++函数名以可理解的方式显示出来。 

--debugging 
-g 
显示调试信息。企图解析保存在文件中的调试信息并以C语言的语法显示出来。仅仅支持某些类型的调试信息。有些其他的格式被readelf -w支持。 

-e 
--debugging-tags 
类似-g选项,但是生成的信息是和ctags工具相兼容的格式。 

--disassemble 
-d 
从objfile中反汇编那些特定指令机器码的section。 

-D 
--disassemble-all 
与 -d 类似,但反汇编所有section. 

--prefix-addresses 
反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式。 

-EB 
-EL 
--endian={big|little} 
指定目标文件的小端。这个项将影响反汇编出来的指令。在反汇编的文件没描述小端信息的时候用。例如S-records. 

-f 
--file-headers 
显示objfile中每个文件的整体头部摘要信息。 

-h 
--section-headers 
--headers 
显示目标文件各个section的头部摘要信息。 

-H 
--help 
简短的帮助信息。 

-i 
--info 
显示对于 -b 或者 -m 选项可用的架构和目标格式列表。 

-j name
--section=name 
仅仅显示指定名称为name的section的信息 

-l
--line-numbers 
用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。 

-m machine 
--architecture=machine 
指定反汇编目标文件时使用的架构,当待反汇编文件本身没描述架构信息的时候(比如S-records),这个选项很有用。可以用-i选项列出这里能够指定的架构. 

--reloc 
-r 
显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇编后的格式显示出来。 

--dynamic-reloc 
-R 
显示文件的动态重定位入口,仅仅对于动态目标文件意义,比如某些共享库。 

-s 
--full-contents 
显示指定section的完整内容。默认所有的非空section都会被显示。 

-S 
--source 
尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。 

--show-raw-insn 
反汇编的时候,显示每条汇编指令对应的机器码,如不指定--prefix-addresses,这将是缺省选项。 

--no-show-raw-insn 
反汇编时,不显示汇编指令的机器码,如不指定--prefix-addresses,这将是缺省选项。 

--start-address=address 
从指定地址开始显示数据,该选项影响-d、-r和-s选项的输出。 

--stop-address=address 
显示数据直到指定地址为止,该项影响-d、-r和-s选项的输出。 

-t 
--syms 
显示文件的符号表入口。类似于nm -s提供的信息 

-T 
--dynamic-syms 
显示文件的动态符号表入口,仅仅对动态目标文件意义,比如某些共享库。它显示的信息类似于 nm -D|--dynamic 显示的信息。 

-V 
--version 
版本信息 

--all-headers 
-x 
显示所可用的头信息,包括符号表、重定位入口。-x 等价于-a -f -h -r -t 同时指定。 

-z 
--disassemble-zeroes 
一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。 

@file 可以将选项集中到一个文件中,然后使用这个@file选项载入。

实例

首先,在给出后面大部分测试所基于的源代码以及编译指令。 源代码如下: 

[root@localhost test]# nl mytest.cpp 
void printTest() {
    char a;
    a = 'a';
}

void printTest2() {
int a = 2;
a+=2;
} 

对以上源代码进行编译,如下: 

[root@localhost test]# g++ -c -g mytest.cpp 

这里,生成的文件是mytest.o,为了方便测试包含了调试的信息,对可执行文件的测试,显示的结果类似。 

查看当前使用的objdump的版本号: 

[root@localhost test]# objdump -V 
GNU objdump 2.17.50.0.6-14.el5 20061020 
Copyright 2005 free Software Foundation, Inc. 
This program is free software; you may redistribute it under the terms of 
the GNU General Public License.  This program has absolutely no warranty. 

查看档案库文件中的信息: 

[root@localhost test]# objdump -a libmy2.a 
In archive libmy2.a: 
myfile.o:     file format elf32-i386 
rwxrwxrwx 0/0   2724 Nov 16 16:06 2009 myfile.o 
mytest.o:     file format elf32-i386 
rw-r--r-- 0/0    727 Jul 13 15:32 2011 mytest.o 

这里,libmy2.a是一个使用ar命令将多个*.o目标文件打包而生成的静态库。命令的输出类似ar -tv,相比较ar -tv输出如下: 

[root@localhost test]# ar -tv libmy2.a 
rwxrwxrwx 0/0   2724 Nov 16 16:06 2009 myfile.o 
rw-r--r-- 0/0    727 Jul 13 15:32 2011 mytest.o 

显示可用的架构和目标结构列表: 

[root@localhost test]# objdump -i 
BFD header file version 2.17.50.0.6-14.el5 20061020 
elf32-i386 
(header little endian, data little endian) 
  i386 
a.out-i386-linux 
(header little endian, data little endian) 
  i386 
efi-app-ia32 
(header little endian, data little endian) 
  i386 
elf64-x86-64 
(header little endian, data little endian) 
  i386 
elf64-little 
(header little endian, data little endian) 
  i386 
elf64-big 
(header big endian, data big endian) 
  i386 
elf32-little 
(header little endian, data little endian) 
  i386 
elf32-big 
(header big endian, data big endian) 
  i386 
srec 
(header endianness unknown, data endianness unknown) 
  i386 
symbolsrec 
(header endianness unknown, data endianness unknown) 
  i386 
tekhex 
(header endianness unknown, data endianness unknown) 
  i386 
binary 
(header endianness unknown, data endianness unknown) 
  i386 
ihex 
(header endianness unknown, data endianness unknown) 
  i386 
trad-core 
(header endianness unknown, data endianness unknown) 

              elf32-i386 a.out-i386-linux efi-app-ia32 elf64-x86-64 
          i386 elf32-i386 a.out-i386-linux efi-app-ia32 elf64-x86-64 

              elf64-little elf64-big elf32-little elf32-big srec symbolsrec 
          i386 elf64-little elf64-big elf32-little elf32-big srec symbolsrec 

              tekhex binary ihex trad-core 
          i386 tekhex binary ihex --------- 

这里,显示的信息是相对于 -b 或者 -m 选项可用的架构和目标格式列表。 

显示mytest.o文件中的text段的内容: 

[root@localhost test]# objdump --section=.text -s mytest.o 
mytest.o:     file format elf32-i386 
Contents of section .text: 
0000 5589e583 ec10c645 ff61c9c3 5589e583  U......E.a..U... 
0010 ec10c745 fc020000 008345fc 02c9c3    ...E......E.... 

这里注意,不能单独使用-j或者–section,例如objdump --section=.text mytest.o是不会运行成功的。 

反汇编mytest.o中的text段内容,并尽可能用源代码形式表示: 

[root@localhost test]# objdump -j .text -S mytest.o 
mytest.o:     file format elf32-i386 
Disassembly of section .text: 
00000000 <_Z9printTestv>: 
void printTest() 
   0:   55                      push   %ebp 
   1:   89 e5                   mov    %esp,%ebp 
   3:   83 ec 10                sub    $0x10,%esp 
{ 
        char a; 
        a = 'a'; 
   6:   c6 45 ff 61             movb   $0x61,0xffffffff(%ebp) 
} 
   a:   c9                      leave  
   b:   c3                      ret    

000000c <_Z10printTest2v>: 
void printTest2() 
   c:   55                      push   %ebp 
   d:   89 e5                   mov    %esp,%ebp 
   f:   83 ec 10                sub    $0x10,%esp 
{ 
        int a = 2; 
  12:   c7 45 fc 02 00 00 00    movl   $0x2,0xfffffffc(%ebp) 
        a+=2; 
  19:   83 45 fc 02             addl   $0x2,0xfffffffc(%ebp) 
} 
  1d:   c9                      leave  
  1e:   c3                      ret    

这里注意,不能单独使用-j或者–section,例如objdump -j .text mytest.o是不会运行成功的。另外-S命令对于包含调试信息的目标文件,显示的效果比较好,如果编译时没有指定g++的-g选项,那么目标文件就不包含调试信息,那么显示效果就差多了。 

反汇编出mytest.o的源代码: 

[root@localhost test]# objdump -S mytest.o 
mytest.o:     file format elf32-i386 

Disassembly of section .text: 

00000000 <_Z9printTestv>: 
void printTest() 
   0:   55                      push   %ebp 
   1:   89 e5                   mov    %esp,%ebp 
   3:   83 ec 10                sub    $0x10,%esp 
{ 
        char a; 
        a = 'a'; 
   6:   c6 45 ff 61             movb   $0x61,0xffffffff(%ebp) 
} 
   a:   c9                      leave  
   b:   c3                      ret    

0000000c <_Z10printTest2v>: 
void printTest2() 
   c:   55                      push   %ebp 
   d:   89 e5                   mov    %esp,%ebp 
   f:   83 ec 10                sub    $0x10,%esp 
{ 
       int a = 2; 
  12:   c7 45 fc 02 00 00 00    movl   $0x2,0xfffffffc(%ebp) 
        a+=2; 
  19:   83 45 fc 02             addl   $0x2,0xfffffffc(%ebp) 
} 
  1d:   c9                      leave  
  1e:   c3                      ret    

这里,尤其当编译的时候指定了-g这种调试参数时,反汇编的效果比较明显。隐含了-d参数。 

显示文件的符号表入口: 

[root@localhost test]# objdump -t mytest.o 
mytest.o:     file format elf32-i386 

SYMBOL TABLE: 
00000000 l    df *ABS*  00000000 mytest.cpp 
00000000 l    d  .text  00000000 .text 
00000000 l    d  .data  00000000 .data 
00000000 l    d  .bss   00000000 .bss 
00000000 l    d  .debug_abbrev  00000000 .debug_abbrev 
00000000 l    d  .debug_info    00000000 .debug_info 
00000000 l    d  .debug_line    00000000 .debug_line 
00000000 l    d  .debug_frame   00000000 .debug_frame 
00000000 l    d  .debug_loc     00000000 .debug_loc 
00000000 l    d  .debug_pubnames        00000000 .debug_pubnames 
00000000 l    d  .debug_aranges 00000000 .debug_aranges 
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack 
00000000 l    d  .comment       00000000 .comment 
00000000 g     F .text  0000000c _Z9printTestv 
00000000         *UND*  00000000 __gxx_personality_v0 
0000000c g     F .text  00000013 _Z10printTest2v 

这里,输出的信息类似nm -s命令的输出,相比较之下,nm命令的输出如下: 

[root@localhost test]# nm -s mytest.o 
0000000c T _Z10printTest2v 
00000000 T _Z9printTestv 
         U __gxx_personality_v0 

显示文件的符号表入口,将底层符号解码并表示成用户级别: 

[root@localhost test]# objdump -t -C mytest.o 
mytest.o:     file format elf32-i386 
SYMBOL TABLE: 
00000000 l    df *ABS*  00000000 mytest.cpp 
00000000 l    d  .text  00000000 .text 
00000000 l    d  .data  00000000 .data 
00000000 l    d  .bss   00000000 .bss 
00000000 l    d  .debug_abbrev  00000000 .debug_abbrev 
00000000 l    d  .debug_info    00000000 .debug_info 
00000000 l    d  .debug_line    00000000 .debug_line 
00000000 l    d  .debug_frame   00000000 .debug_frame 
00000000 l    d  .debug_loc     00000000 .debug_loc 
00000000 l    d  .debug_pubnames        00000000 .debug_pubnames 
00000000 l    d  .debug_aranges 00000000 .debug_aranges 
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack 
00000000 l    d  .comment       00000000 .comment 
00000000 g     F .text  0000000c printTest() 
00000000         *UND*  00000000 __gxx_personality_v0 
0000000c g     F .text  00000013 printTest2() 

这里,和没-C相比,printTest2函数可读性增加了。 

反汇编目标文件的特定机器码段: 

[root@localhost test]# objdump -d mytest.o 
mytest.o:     file format elf32-i386 
Disassembly of section .text: 

00000000 <_Z9printTestv>: 
   0:   55                      push   %ebp 
   1:   89 e5                   mov    %esp,%ebp 
   3:   83 ec 10                sub    $0x10,%esp 
   6:   c6 45 ff 61             movb   $0x61,0xffffffff(%ebp) 
   a:   c9                      leave  
  b:   c3                      ret    

0000000c <_Z10printTest2v>: 
   c:   55                      push   %ebp 
   d:   89 e5                   mov    %esp,%ebp 
   f:   83 ec 10                sub    $0x10,%esp 
  12:   c7 45 fc 02 00 00 00    movl   $0x2,0xfffffffc(%ebp) 
  19:   83 45 fc 02             addl   $0x2,0xfffffffc(%ebp) 
  1d:   c9                      leave  
  1e:   c3                      ret    

这里,对text段的内容进行了反汇编。 

反汇编特定段,并将汇编代码对应的文件名称和行号对应上: 

[root@localhost test]# objdump -d -l mytest.o
mytest.o:     file format elf32-i386 
Disassembly of section .text: 

00000000 <_Z9printTestv>: 
_Z9printTestv(): 
/root/test/04_libraryTest/mytest.cpp:1 
   0:   55                      push   %ebp 
   1:   89 e5                   mov    %esp,%ebp 
   3:   83 ec 10                sub    $0x10,%esp 
/root/test/04_libraryTest/mytest.cpp:4 
   6:   c6 45 ff 61             movb   $0x61,0xffffffff(%ebp) 
/root/test/04_libraryTest/mytest.cpp:5 
   a:   c9                      leave  
   b:   c3                      ret    

0000000c <_Z10printTest2v>: 
_Z10printTest2v(): 
/root/test/04_libraryTest/mytest.cpp:6 
   c:   55                      push   %ebp 
   d:   89 e5                   mov    %esp,%ebp 
   f:   83 ec 10                sub    $0x10,%esp 
/root/test/04_libraryTest/mytest.cpp:8 
  12:   c7 45 fc 02 00 00 00    movl   $0x2,0xfffffffc(%ebp) 
/root/test/04_libraryTest/mytest.cpp:9 
  19:   83 45 fc 02             addl   $0x2,0xfffffffc(%ebp) 
/root/test/04_libraryTest/mytest.cpp:10 
  1d:   c9                      leave  
  1e:   c3                      ret    

这里,项"-d"从objfile中反汇编那些特定指令机器码的section,而使用"-l"指定用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用,使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。 

显示目标文件各个段的头部摘要信息: 

[root@localhost test]# objdump -h mytest.o 
mytest.o:     file format elf32-i386 

Sections: 
Idx Name          Size      VMA       LMA       File off  Algn 
  0 .text         0000001f  00000000  00000000  00000034  2**2 
                  CONTENTS, ALLOC, LOAD, readonly, CODE 
  1 .data         00000000  00000000  00000000  00000054  2**2 
                  CONTENTS, ALLOC, LOAD, DATA 
  2 .bss          00000000  00000000  00000000  00000054  2**2 
                  ALLOC 
  3 .debug_abbrev 00000046  00000000  00000000  00000054  2**0 
                  CONTENTS, READONLY, DEBUGGING 
  4 .debug_info   000000ed  00000000  00000000  0000009a  2**0 
                  CONTENTS, RELOC, READONLY, DEBUGGING 
  5 .debug_line   0000003e  00000000  00000000  00000187  2**0 
                  CONTENTS, RELOC, READONLY, DEBUGGING 
  6 .debug_frame  00000044  00000000  00000000  000001c8  2**2 
                  CONTENTS, RELOC, READONLY, DEBUGGING 
  7 .debug_loc    00000058  00000000  00000000  0000020c  2**0 
                  CONTENTS, READONLY, DEBUGGING 
  8 .debug_pubnames 0000002f  00000000  00000000  00000264  2**0 
                  CONTENTS, RELOC, READONLY, DEBUGGING 
  9 .debug_aranges 00000020  00000000  00000000  00000293  2**0 
                  CONTENTS, RELOC, READONLY, DEBUGGING 
10 .comment      0000002e  00000000  00000000  000002b3  2**0 
                  CONTENTS, READONLY 
11 .note.GNU-stack 00000000  00000000  00000000  000002e1  2**0 
                  CONTENTS, READONLY 

这里,更多的内容参见man objdump中的这个选项。

 

readelf

readelf命令用来显示一个或者多个elf格式的目标文件的信息,可以通过它的选项来控制显示哪些信息。这里的elf-file(s)就表示那些被检查的文件。可以支持32位,64位的elf格式文件,也支持包含elf文件的文档(这里一般指的是使用ar命令将一些elf文件打包之后生成的例如lib*.a之类的“静态库”文件)。 

这个程序和objdump提供的功能类似,但是它显示的信息更为具体,并且它不依赖BFD库(BFD库是一个GNU项目,它的目标就是希望通过一种统一的接口来处理不同的目标文件),所以即使BFD库有什么bug存在的话也不会影响到readelf程序。 

运行readelf的时候,除了-v和-H之外,其它的选项必须有一个被指定。 

ELF文件类型

种类型的ELF文件:

  1. 可重定位文件:用户和其他目标文件一起创建可执行文件或者共享目标文件,例如lib*.a文件。 
  2. 可执行文件:用于生成进程映像,载入内存执行,例如编译好的可执行文件a.out。 
  3. 共享目标文件:用于和其他共享目标文件或者可重定位文件一起生成elf目标文件或者和执行文件一起创建进程映像,例如lib*.so文件。 

ELF文件作用:

ELF文件参与程序的连接(建立一个程序)和程序的执行(运行一个程序),所以可以从不同的角度来看待elf格式的文件: 

  1. 如果用于编译和链接(可重定位文件),则编译器和链接器将把elf文件看作是节头表描述的节的集合,程序头表可选。 
  2. 如果用于加载执行(可执行文件),则加载器则将把elf文件看作是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。 
  3. 如果是共享文件,则两者都含有。 

ELF文件总体组成: 

elf文件头描述elf文件的总体信息。包括:系统相关,类型相关,加载相关,链接相关。 

  • 系统相关表示:elf文件标识的魔术数,以及硬件和平台等相关信息,增加了elf文件的移植性,使交叉编译成为可能。 
  • 类型相关就是前面说的那个类型。 
  • 加载相关:包括程序头表相关信息。 
  • 链接相关:节头表相关信息。 

选项

-a 
--all 显示全部信息,等价于 -h -l -S -s -r -d -V -A -I. 

-h 
--file-header 显示elf文件开始的文件头信息. 

-l 
--program-headers  
--segments 显示程序头(段头)信息(如果有的话)。 

-S 
--section-headers  
--sections 显示节头信息(如果有的话)。 

-g 
--section-groups 显示节组信息(如果有的话)。 

-t 
--section-details 显示节的详细信息(-S的)。 

-s 
--syms        
--symbols 显示符号表段中的项(如果有的话)。 

-e 
--headers 显示全部头信息,等价于: -h -l -S 

-n 
--notes 显示note段(内核注释)的信息。 

-r 
--relocs 显示可重定位段的信息。 

-u 
--unwind 显示unwind段信息。当前只支持IA64 ELF的unwind段信息。 

-d 
--dynamic 显示动态段的信息。 

-V 
--version-info 显示版本段的信息。 

-A 
--arch-specific 显示CPU构架信息。 

-D 
--use-dynamic 使用动态段中的符号表显示符号,而不是使用符号段。 

-x <number or name> 
--hex-dump=<number or name> 以16进制方式显示指定段内内容。number指定段表中段的索引,或字符串指定文件中的段名。 

-w[liaprmfFsoR] or 
--debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges] 显示调试段中指定的内容。 

-I 
--histogram 显示符号的时候,显示bucket list长度的柱状图。 

-v 
--version 显示readelf的版本信息。 

-H 
--help 显示readelf所支持的命令行选项。 

-W 
--wide 宽行输出。 

@file 可以将选项集中到一个文件中,然后使用这个@file选项载入。 

实例

先给出如下例子:

1.对于可执行文件形式的elf格式文件:

1)查看可执行程序的源代码如下: 

[root@localhost test]$ cat main.cpp 
#include <iostream> 
using std::cout; 
using std::endl; 
void my_print(); 

int main(int argc, char *argv[]) 
{ 
        my_print(); 
        cout<<"hello!"<<endl; 
        return 0; 
} 

void  my_print() 
{ 
        cout<<"print!"<<endl; 
} 

2)编译如下: 

[root@localhost test]$ g++ main.cpp -o main 
[root@localhost test]$ g++ -g main.cpp -o main.debug 

3)编译之后,查看生成的文件: 

[root@localhost test]$ ls -l 
总计 64 
-rwxr-xr-x 1 quietheart quietheart  6700 07-07 18:04 main 
-rw-r--r-- 1 quietheart quietheart   201 07-07 18:02 main.cpp 
-rwxr-xr-x 1 quietheart quietheart 38932 07-07 18:04 main.debug 

这里,main.debug是带有调试信息的可执行文件,main是一般的可执行文件。 

2.对于库文件形式的elf格式文件:

1)查看库的源代码如下: 

//myfile.h 
#ifndef __MYFILE_H 
#define __MYFILE_H 
void printInfo(); 
#endif 

//myfile.cpp 
#include "myfile.h" 
#include <iostream> 
using std::cout; 
using std::endl; 
void printInfo() 
{ 
    cout<<"hello"<<endl; 
} 

2)编译如下: 

[root@localhost test]$ g++ -c myfile.cpp 
[root@localhost test]$ g++ -shared -fPCI -o libmy.so myfile.o 
[root@localhost test]$ ar -r libmy.a myfile.o 
ar: creating libmy.a 

3)编译之后,查看生成的文件: 

[root@localhost test]$ ls -l 

总计 44 

-rw-r--r-- 1 quietheart quietheart 2154 07-08 16:14 libmy.a 
-rwxr-xr-x 1 quietheart quietheart 5707 07-08 16:08 libmy.so 
-rwxr-xr-x 1 quietheart quietheart  117 07-08 16:06 myfile.cpp 
-rwxr-xr-x 1 quietheart quietheart   63 07-08 16:08 myfile.h 
-rw-r--r-- 1 quietheart quietheart 2004 07-08 16:08 myfile.o 
libmy.a  libmy.so  myfile.cpp  myfile.h  myfile.o 

这里,分别生成目标文件myfile.o,共享库文件libmy.so,和静态库文件libmy.a。 

基于以上可执行文件和库,这里给出一些常用的命令。 

读取可执行文件形式的elf文件头信息:

[root@localhost test]$ readelf -h main 
ELF Header: 
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32 
  Data:                              2's complement, little endian 
  Version:                           1 (current) 
  OS/ABI:                            UNIX - System V 
  ABI Version:                       0 
  type:                              exec (Executable file) 
  Machine:                           Intel 80386 
  Version:                           0x1 
  Entry point address:               0x8048580 
  Start of program headers:          52 (bytes into file) 
  Start of section headers:          3232 (bytes into file) 
  Flags:                             0x0 
  Size of this header:               52 (bytes) 
  Size of program headers:           32 (bytes) 
  Number of program headers:         8 
  Size of section headers:           40 (bytes) 
  Number of section headers:         29 
  Section header string table index: 26 

这里,可见可执行文件的elf文件,其类型为EXEC(可执行文件)。另外,含调试信息的"main.debug"和不含调试信息的"main"除了一些大小信息之外,其内容是一样的。并且由此可见文件的体系结构为Intel 80386。 

读取目标文件形式的elf文件头信息:

[root@localhost test]$ readelf -h myfile.o 
ELF Header: 
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32 
  Data:                              2's complement, little endian 
  Version:                           1 (current) 
  OS/ABI:                            UNIX - System V 
  ABI Version:                       0 
  Type:                              REL (Relocatable file) 
  Machine:                           Intel 80386 
  Version:                           0x1 
  Entry point address:               0x0 
  Start of program headers:          0 (bytes into file) 
  Start of section headers:          516 (bytes into file) 
  Flags:                             0x0 
  Size of this header:               52 (bytes) 
  Size of program headers:           0 (bytes) 
  Number of program headers:         0 
  Size of section headers:           40 (bytes) 
  Number of section headers:         15 
  Section header string table index: 12 

这里,可见目标文件的elf文件,其类型为REL(可重定位文件)。 

读取静态库文件形式的elf文件头信息:

[root@localhost test]$ readelf -h libmy.a 
File: libmy.a(myfile.o) 
ELF Header: 
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32 
  Data:                              2's complement, little endian 
  Version:                           1 (current) 
  OS/ABI:                            UNIX - System V 
  ABI Version:                       0 
  Type:                              REL (Relocatable file) 
  Machine:                           Intel 80386 
  Version:                           0x1 
  Entry point address:               0x0 
  Start of program headers:          0 (bytes into file) 
  Start of section headers:          516 (bytes into file) 
  Flags:                             0x0 
  Size of this header:               52 (bytes) 
  Size of program headers:           0 (bytes) 
  Number of program headers:         0 
  Size of section headers:           40 (bytes) 
  Number of section headers:         15 
  Section header string table index: 12 

这里,可见静态库文件的elf文件,其类型为REL(可重定位文件)。 

读取动态库文件形式的elf文件头信息:

[root@localhost test]$ readelf -h libmy.so 
ELF Header: 
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32 
  Data:                              2's complement, little endian 
  Version:                           1 (current) 
  OS/ABI:                            UNIX - System V 
  ABI Version:                       0 
  Type:                              DYN (Shared object file) 
  Machine:                           Intel 80386 
  Version:                           0x1 
  Entry point address:               0x550 
  Start of program headers:          52 (bytes into file) 
  Start of section headers:          2768 (bytes into file) 
  Flags:                             0x0 
  Size of this header:               52 (bytes) 
  Size of program headers:           32 (bytes) 
  Number of program headers:         5 
  Size of section headers:           40 (bytes) 
  Number of section headers:         27 
  Section header string table index: 24 

这里,可见动态库文件的elf文件,其类型为DYN(共享目标文件)。 

查看可执行的elf文件程序头表信息:

[root@localhost test]$ readelf -l main 
Elf file type is EXEC (Executable file) 
Entry point 0x8048580 
There are 8 program headers, starting at offset 52 

Program Headers: 
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align 
  PHDR           0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4 
  INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1 
      [Requesting program interpreter: /lib/ld-linux.so.2] 
  LOAD           0x000000 0x08048000 0x08048000 0x00970 0x00970 R E 0x1000 
  LOAD           0x000970 0x08049970 0x08049970 0x00130 0x001c8 RW  0x1000 
  DYNAMIC        0x000988 0x08049988 0x08049988 0x000e0 0x000e0 RW  0x4 
  NOTE           0x000148 0x08048148 0x08048148 0x00020 0x00020 R   0x4 
  GNU_EH_FRAME   0x000820 0x08048820 0x08048820 0x00044 0x00044 R   0x4 
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4 

Section to Segment mapping: 
  Segment Sections... 
   00     
   01     .interp 
   02     .interp .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag 
   06     .eh_frame_hdr 
   07     

这里,含调试信息的"main.debug"和不含调试信息的"main"其内容是一样的。 

查看目标文件的elf文件程序头表信息: 

[root@localhost test]$ readelf -l myfile.o 
There are no program headers in this file. 

这里可知,可重定位的目标文件,它没程序头表。 

查看静态库文件的elf文件程序头表信息:

[root@localhost test]$ readelf -l libmy.a 
File: libmy.a(myfile.o) 
There are no program headers in this file. 

这里可知,可重定位的静态库文件,它没程序头表。 

查看动态库文件的elf文件程序头表信息:

[root@localhost test]$ readelf -l libmy.so 
Elf file type is DYN (Shared object file) 
Entry point 0x550 
There are 5 program headers, starting at offset 52 

Program Headers: 
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align 
  LOAD           0x000000 0x00000000 0x00000000 0x007f4 0x007f4 R E 0x1000 
  LOAD           0x0007f4 0x000017f4 0x000017f4 0x0011c 0x00128 RW  0x1000 
  DYNAMIC        0x000810 0x00001810 0x00001810 0x000e0 0x000e0 RW  0x4 
  GNU_EH_FRAME   0x000738 0x00000738 0x00000738 0x0002c 0x0002c R   0x4 
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4 

Section to Segment mapping: 
  Segment Sections... 
   00     .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   01     .ctors .dtors .jcr .data.rel.ro .dynamic .got .got.plt .bss 
   02     .dynamic 
   03     .eh_frame_hdr 
   04     

这里可知,做为共享目标文件的动态库,它程序头表。 

查看一个可执行的elf文件的节信息:

[root@localhost test]$ readelf -S main 
There are 29 section headers, starting at offset 0xca0: 
Section Headers: 
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al 
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1 
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4 
  [ 3] .gnu.hash         GNU_HASH        08048168 000168 000030 04   A  4   0  4 
  [ 4] .dynsym           DYNSYM          08048198 000198 0000d0 10   A  5   1  4 
  [ 5] .dynstr           STRTAB          08048268 000268 000183 00   A  0   0  1 
  [ 6] .gnu.version      VERSYM          080483ec 0003ec 00001a 02   A  4   0  2 
  [ 7] .gnu.version_r    VERNEED         08048408 000408 000060 00   A  5   2  4 
  [ 8] .rel.dyn          REL             08048468 000468 000010 08   A  4   0  4 
  [ 9] .rel.plt          REL             08048478 000478 000048 08   A  4  11  4 
  [10] .init             PROGBITS        080484c0 0004c0 000017 00  AX  0   0  4 
  [11] .plt              PROGBITS        080484d8 0004d8 0000a0 04  AX  0   0  4 
  [12] .text             PROGBITS        08048580 000580 000268 00  AX  0   0 16 
  [13] .fini             PROGBITS        080487e8 0007e8 00001c 00  AX  0   0  4 
  [14] .rodata           PROGBITS        08048804 000804 00001a 00   A  0   0  4 
  [15] .eh_frame_hdr     PROGBITS        08048820 000820 000044 00   A  0   0  4 
  [16] .eh_frame         PROGBITS        08048864 000864 00010c 00   A  0   0  4 
  [17] .ctors            PROGBITS        08049970 000970 00000c 00  WA  0   0  4 
  [18] .dtors            PROGBITS        0804997c 00097c 000008 00  WA  0   0  4 
  [19] .jcr              PROGBITS        08049984 000984 000004 00  WA  0   0  4 
  [20] .dynamic          DYNAMIC         08049988 000988 0000e0 08  WA  5   0  4 
  [21] .got              PROGBITS        08049a68 000a68 000004 04  WA  0   0  4 
  [22] .got.plt          PROGBITS        08049a6c 000a6c 000030 04  WA  0   0  4 
  [23] .data             PROGBITS        08049a9c 000a9c 000004 00  WA  0   0  4 
  [24] .bss              NOBITS          08049aa0 000aa0 000098 00  WA  0   0  8 
  [25] .comment          PROGBITS        00000000 000aa0 000114 00      0   0  1 
  [26] .shstrtab         STRTAB          00000000 000bb4 0000e9 00      0   0  1 
  [27] .symtab           SYMTAB          00000000 001128 000510 10     28  53  4 
  [28] .strtab           STRTAB          00000000 001638 0003f4 00      0   0  1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings) 
  I (info), L (link order), G (group), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 

这里,main是可执行文件,不含调试信息。 

查看一个包含调试信息的可执行的elf文件的节信息:

[root@localhost test]$ readelf -S main.debug 
There are 37 section headers, starting at offset 0x88c8: 

Section Headers: 
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al 
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1 
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4 
  [ 3] .gnu.hash         GNU_HASH        08048168 000168 000030 04   A  4   0  4 
  [ 4] .dynsym           DYNSYM          08048198 000198 0000d0 10   A  5   1  4 
  [ 5] .dynstr           STRTAB          08048268 000268 000183 00   A  0   0  1 
  [ 6] .gnu.version      VERSYM          080483ec 0003ec 00001a 02   A  4   0  2 
  [ 7] .gnu.version_r    VERNEED         08048408 000408 000060 00   A  5   2  4 
  [ 8] .rel.dyn          REL             08048468 000468 000010 08   A  4   0  4 
  [ 9] .rel.plt          REL             08048478 000478 000048 08   A  4  11  4 
  [10] .init             PROGBITS        080484c0 0004c0 000017 00  AX  0   0  4 
  [11] .plt              PROGBITS        080484d8 0004d8 0000a0 04  AX  0   0  4 
  [12] .text             PROGBITS        08048580 000580 000268 00  AX  0   0 16 
  [13] .fini             PROGBITS        080487e8 0007e8 00001c 00  AX  0   0  4 
  [14] .rodata           PROGBITS        08048804 000804 00001a 00   A  0   0  4 
  [15] .eh_frame_hdr     PROGBITS        08048820 000820 000044 00   A  0   0  4 
  [16] .eh_frame         PROGBITS        08048864 000864 00010c 00   A  0   0  4 
  [17] .ctors            PROGBITS        08049970 000970 00000c 00  WA  0   0  4 
  [18] .dtors            PROGBITS        0804997c 00097c 000008 00  WA  0   0  4 
  [19] .jcr              PROGBITS        08049984 000984 000004 00  WA  0   0  4 
  [20] .dynamic          DYNAMIC         08049988 000988 0000e0 08  WA  5   0  4 
  [21] .got              PROGBITS        08049a68 000a68 000004 04  WA  0   0  4 
  [22] .got.plt          PROGBITS        08049a6c 000a6c 000030 04  WA  0   0  4 
  [23] .data             PROGBITS        08049a9c 000a9c 000004 00  WA  0   0  4 
  [24] .bss              NOBITS          08049aa0 000aa0 000098 00  WA  0   0  8 
  [25] .comment          PROGBITS        00000000 000aa0 000114 00      0   0  1 
  [26] .debug_aranges    PROGBITS        00000000 000bb4 000020 00      0   0  1 
  [27] .debug_pubnames   PROGBITS        00000000 000bd4 000028 00      0   0  1 
  [28] .debug_info       PROGBITS        00000000 000bfc 0067aa 00      0   0  1 
  [29] .debug_abbrev     PROGBITS        00000000 0073a6 000726 00      0   0  1 
  [30] .debug_line       PROGBITS        00000000 007acc 0003e1 00      0   0  1 
  [31] .debug_frame      PROGBITS        00000000 007eb0 00009c 00      0   0  4 
  [32] .debug_str        PROGBITS        00000000 007f4c 000735 00      0   0  1 
  [33] .debug_loc        PROGBITS        00000000 008681 0000f3 00      0   0  1 
  [34] .shstrtab         STRTAB          00000000 008774 000151 00      0   0  1 
  [35] .symtab           SYMTAB          00000000 008e90 000590 10     36  61  4 
  [36] .strtab           STRTAB          00000000 009420 0003f4 00      0   0  1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings) 
  I (info), L (link order), G (group), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 

可见,相对非调试版本的可执行文件,多了".debug*"段的信息。 

查看一个目标文件的elf文件的节信息:

[root@localhost test]$ readelf -S myfile.o 
There are 15 section headers, starting at offset 0x204: 

Section Headers: 
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al 
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 
  [ 1] .text             PROGBITS        00000000 000034 00009e 00  AX  0   0  4 
  [ 2] .rel.text         REL             00000000 000744 000060 08     13   1  4 
  [ 3] .data             PROGBITS        00000000 0000d4 000000 00  WA  0   0  4 
  [ 4] .bss              NOBITS          00000000 0000d4 000001 00  WA  0   0  4 
  [ 5] .ctors            PROGBITS        00000000 0000d4 000004 00  WA  0   0  4 
  [ 6] .rel.ctors        REL             00000000 0007a4 000008 08     13   5  4 
  [ 7] .rodata           PROGBITS        00000000 0000d8 000006 00   A  0   0  1 
  [ 8] .eh_frame         PROGBITS        00000000 0000e0 00008c 00   A  0   0  4 
  [ 9] .rel.eh_frame     REL             00000000 0007ac 000028 08     13   8  4 
  [10] .comment          PROGBITS        00000000 00016c 00002e 00      0   0  1 
  [11] .note.GNU-stack   PROGBITS        00000000 00019a 000000 00      0   0  1 
  [12] .shstrtab         STRTAB          00000000 00019a 00006a 00      0   0  1 
  [13] .symtab           SYMTAB          00000000 00045c 000180 10     14  14  4 
  [14] .strtab           STRTAB          00000000 0005dc 000166 00      0   0  1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings) 
  I (info), L (link order), G (group), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 

查看一个静态库文件的elf文件的节信息:

[root@localhost test]$ readelf -S libmy.a 
File: libmy.a(myfile.o) 
There are 15 section headers, starting at offset 0x204: 

Section Headers: 
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al 
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 
  [ 1] .text             PROGBITS        00000000 000034 00009e 00  AX  0   0  4 
  [ 2] .rel.text         REL             00000000 000744 000060 08     13   1  4 
  [ 3] .data             PROGBITS        00000000 0000d4 000000 00  WA  0   0  4 
  [ 4] .bss              NOBITS          00000000 0000d4 000001 00  WA  0   0  4 
  [ 5] .ctors            PROGBITS        00000000 0000d4 000004 00  WA  0   0  4 
  [ 6] .rel.ctors        REL             00000000 0007a4 000008 08     13   5  4 
  [ 7] .rodata           PROGBITS        00000000 0000d8 000006 00   A  0   0  1 
  [ 8] .eh_frame         PROGBITS        00000000 0000e0 00008c 00   A  0   0  4 
  [ 9] .rel.eh_frame     REL             00000000 0007ac 000028 08     13   8  4 
  [10] .comment          PROGBITS        00000000 00016c 00002e 00      0   0  1 
  [11] .note.GNU-stack   PROGBITS        00000000 00019a 000000 00      0   0  1 
  [12] .shstrtab         STRTAB          00000000 00019a 00006a 00      0   0  1 
  [13] .symtab           SYMTAB          00000000 00045c 000180 10     14  14  4 
  [14] .strtab           STRTAB          00000000 0005dc 000166 00      0   0  1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings) 
  I (info), L (link order), G (group), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 

查看一个动态库文件的elf文件的节信息:

[root@localhost test]$ readelf -S libmy.so 
There are 27 section headers, starting at offset 0xad0: 

Section Headers: 
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al 
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 
  [ 1] .gnu.hash         GNU_HASH        000000d4 0000d4 00003c 04   A  2   0  4 
  [ 2] .dynsym           DYNSYM          00000110 000110 000120 10   A  3   1  4 
  [ 3] .dynstr           STRTAB          00000230 000230 000199 00   A  0   0  1 
  [ 4] .gnu.version      VERSYM          000003ca 0003ca 000024 02   A  2   0  2 
  [ 5] .gnu.version_r    VERNEED         000003f0 0003f0 000050 00   A  3   2  4 
  [ 6] .rel.dyn          REL             00000440 000440 0000b0 08   A  2   0  4 
  [ 7] .rel.plt          REL             000004f0 0004f0 000010 08   A  2   9  4 
  [ 8] .init             PROGBITS        00000500 000500 000017 00  AX  0   0  4 
  [ 9] .plt              PROGBITS        00000518 000518 000030 04  AX  0   0  4 
  [10] .text             PROGBITS        00000550 000550 0001c4 00  AX  0   0 16 
  [11] .fini             PROGBITS        00000714 000714 00001c 00  AX  0   0  4 
  [12] .rodata           PROGBITS        00000730 000730 000006 00   A  0   0  1 
  [13] .eh_frame_hdr     PROGBITS        00000738 000738 00002c 00   A  0   0  4 
  [14] .eh_frame         PROGBITS        00000764 000764 000090 00   A  0   0  4 
  [15] .ctors            PROGBITS        000017f4 0007f4 00000c 00  WA  0   0  4 
  [16] .dtors            PROGBITS        00001800 000800 000008 00  WA  0   0  4 
  [17] .jcr              PROGBITS        00001808 000808 000004 00  WA  0   0  4 
  [18] .data.rel.ro      PROGBITS        0000180c 00080c 000004 00  WA  0   0  4 
  [19] .dynamic          DYNAMIC         00001810 000810 0000e0 08  WA  3   0  4 
  [20] .got              PROGBITS        000018f0 0008f0 00000c 04  WA  0   0  4 
  [21] .got.plt          PROGBITS        000018fc 0008fc 000014 04  WA  0   0  4 
  [22] .bss              NOBITS          00001910 000910 00000c 00  WA  0   0  4 
  [23] .comment          PROGBITS        00000000 000910 0000e6 00      0   0  1 
  [24] .shstrtab         STRTAB          00000000 0009f6 0000da 00      0   0  1 
  [25] .symtab           SYMTAB          00000000 000f08 000410 10     26  48  4 
  [26] .strtab           STRTAB          00000000 001318 000333 00      0   0  1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings) 
  I (info), L (link order), G (group), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 

ldconfig

ldconfig命令的用途主要是在默认搜寻目录/lib/usr/lib以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件。缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表,为了让动态链接库为系统所共享,需运行动态链接库的管理命令ldconfig,此执行程序存放在/sbin目录下。

ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令。

语法

ldconfig [-v|--verbose] [-n] [-N] [-X] [-f CONF] [-C CACHE] [-r ROOT] [-l] [-p|--print-cache] [-c FORMAT] [--format=FORMAT] [-V] [-?|--help|--usage] path... 

选项

-v或--verbose:用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字。
-n:用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录。
-N:此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache),若未用-X选项,ldconfig照常更新文件的连接。
-X:此选项指示ldconfig不更新文件的连接,若未用-N选项,则缓存文件正常更新。
-f CONF:此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf。
-C CACHE:此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表。
-r ROOT:此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的)。选择此项时,系统默认的配置文件/etc/ld.so.conf,实际对应的为ROOT/etc/ld.so.conf。如用-r /usr/zzz时,打开配置文件/etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件。用此选项,可以大大增加动态链接库管理的灵活性。
-l:通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接,选择此项时,将进入专家模式,需要手工设置连接,一般用户不用此项。
-p或--print-cache:此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字。
-c FORMAT 或 --format=FORMAT:此选项用于指定缓存文件所使用的格式,共有三种:old(老格式),new(新格式)和compat(兼容格式,此为默认格式)。
-V:此选项打印出ldconfig的版本信息,而后退出。
-? 或 --help 或 --usage:这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出。

ldconfig几个需要注意的地方:

  1. /lib/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig,不然这个library会找不到。
  2. 想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到。
  3. 比如安装了一个mysql/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在程序运行时被找到。
  4. 如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用。
  5. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
  6. 总之,就是不管做了什么关于library的变动后,最好都ldconfig一下,不然会出现一些意想不到的结果。不会花太多的时间,但是会省很多的事。
  7. 再有,诸如libdb-4.3.so文件头中是会含有库名相关的信息的(即含“libdb-4.3.so”,可用strings命令察看),因此仅通过修改文件名以冒充某已被识别的库(如libdb-4.8.so)是行不通的。为此可在编译库的Makefile中直接修改配置信息,指定特别的库名。