注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

几个非常有用的LINUX命令  

2014-03-24 14:56:15|  分类: LINUX编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

几个非常有用的LINUX命令

在最近的开发过程中,发现有三个命令非常有用,写下来,以咨为记。这三个命令是:ldd nmstrace。这三个命令的主要功能如下:

一、ldd:(其实更严格意义上来说,他只是一个脚本)查看当前文件依赖的库和文件,在 ldd 命令打印的结果中,“=>”左边的表示该程序需要连接的共享库之 so 名称,右边表示由 Linux 的共享库系统找到的对应的共享库在文件系统中的具体位置。默认情况下,/etc/ld.so.conf 文件中包含有默认的共享库搜索路径。

在这里需要说明一下:一般来说你可以在这个文件里增加自己的库的说明,但是推荐在ld.so.conf.d文件夹下,新建立一个自己的文件,以.conf为后缀,在这个里面增加自己的库的路径的指定。

详细的命令选项(或者参看maninfo)

$ ldd --help

Usage: ldd [OPTION]... FILE...

      --help              print this help and exit

      --version           print version information and exit

  -d, --data-relocs       process data relocations

  -r, --function-relocs   process data and function relocations

  -u, --unused            print unused direct dependencies

  -v, --verbose           print all information

For bug reporting instructions, please see:

<http://www.debian.org/Bugs/>.

其使用如下:

lib$ ldd -d libsocketcomm.so(或者:ldd xxx.so >> xxx.txt)

         linux-gate.so.1 =>  (0xb7756000)

         libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb763b000)

         libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb761e000)

         libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7473000)

         libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7447000)

         /lib/ld-linux.so.2 (0xb7757000)

二、nm:列出目标文件的符号清单,可以用来查看库导出的函数,与WIN下的DEPENDS类似。

nm命令的格式: nm [-a|--debug-syms] [-g|--extern-only] [-B][-C|--demangle] [-D|--dynamic] [-s|--print-armap][-o|--print-file-name] [-n|--numeric-sort][-p|--no-sort] [-r|--reverse-sort] [--size-sort][-u|--undefined-only] [-l|--line-numbers] [--help][--version] [-t radix|--radix=radix][-P|--portability] [-f format|--format=format][--target=bfdname] [objfile...]

如果没有为nm命令指出目标文件,则nm假定目标文件是a.out。下面列出该命令的任选项,大部分支持“-”开头的短格式和“—“开头的长格式。

-A-o--print-file-name:在找到的各个符号的名字前加上文件名,而不是在此文件的所有符号前只出现文件名一次。

-a--debug-syms:显示调试符号。

-B:等同于--format=bsd,用来兼容MIPSnm

-C--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。

-D--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。

-f format:使用format格式输出。format可以选取bsdsysvposix,该选项在GNUnm中有用。默认为bsd

-g--extern-only:仅显示外部符号。

-n-v--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。

-p--no-sort:按目标文件中遇到的符号顺序显示,不排序。

-P--portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix

-s--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。

-r--reverse-sort:反转排序的顺序(例如,升序变为降序)

--size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。

-t radix--radix=radix:使用radix进制显示符号值。radix只能为“d”表示十进制、“o”表示八进制或“x”表示十六进制。

--target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。

-u--undefined-only:仅显示没有定义的符号(那些外部符号)

-l--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。

-V--version:显示nm的版本号。

--help:显示nm的任选项。

使用方法如下:(为了方便,使用了MORE

或者:nm xxx.so >> xxx.txt

virtual-machine:~/IKEmbX00/03 Code/SocketComm/lib$ nm libsocketcomm.so |more

00019ee8 a _DYNAMIC

00019ff4 a _GLOBAL_OFFSET_TABLE_

         w _ITM_deregisterTMCloneTable

         w _ITM_registerTMCloneTable

         w _Jv_RegisterClasses

         U _Unwind_Resume@@GCC_3.0

0001119a t _ZL15__gthread_equalmm

0000eccc t _ZL18__gthread_active_pv

00010070 t _ZL18__gthread_active_pv

00011188 t _ZL18__gthread_active_pv

0000ecde t _ZL20__gthread_mutex_lockP15pthread_mutex_t

00010082 t _ZL20__gthread_mutex_lockP15pthread_mutex_t

000111b4 t _ZL20__gthread_mutex_lockP15pthread_mutex_t

0000ed06 t _ZL22__gthread_mutex_unlockP15pthread_mutex_t

000100aa t _ZL22__gthread_mutex_unlockP15pthread_mutex_t

000111dc t _ZL22__gthread_mutex_unlockP15pthread_mutex_t

00013b70 r _ZL6g_port

00013b8c r _ZL6g_port

00013c44 r _ZL6g_port

00013cb8 r _ZL6g_port

00013d94 r _ZL6g_port

00013ef0 r _ZL6g_port

00013b6c r _ZL9g_limitFd

三、strace:追踪用户从用户空间发出的系统调用,并以符号表来对调用参数进行表现。他的好处在于不用对于内核做任何的设置。

命令格式:

strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ...

[ -ofile ] [ -ppid ] ... [ -sstrsize ] [ -uusername ] [ command [ arg ... ] ]

strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg ... ] ]

参数:

 

-c -- count time, calls, and errors for each syscall and report summary

 

-f -- follow forks, -ff -- with output into separate files

 

-F -- attempt to follow vforks, -h -- print help message

 

-i -- print instruction pointer at time of syscall

 

-q -- suppress messages about attaching, detaching, etc.

 

-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs

 

-T -- print time spent in each syscall, -V -- print version

 

-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args

 

-x -- print non-ascii strings in hex, -xx -- print all strings in hex

 

-a column -- alignment COLUMN for printing syscall results (default 40)

 

-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...

 

   options: trace, abbrev, verbose, raw, signal, read, or write

 

-o file -- send trace output to FILE instead of stderr

 

-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs

 

-p pid -- trace process with process id PID, may be repeated

 

-s strsize -- limit length of print strings to STRSIZE chars (default 32)

 

-S sortby -- sort syscall counts by: time, calls, name, nothing (default time)

 

-u username -- run command as username handling setuid and/or setgid

 

-E var=val -- put var=val in the environment for command

 

-E var -- remove var from the environment for command

使用的方法:

如果过多,可以使用 strace –o  xxx.txt  xxx

即把输出结果输出到指定的TXT文件中。

execve("./mytest", ["./mytest"], [/* 55 vars */]) = 0

brk(0)                                  = 0x950e000

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)

mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb772b000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=78351, ...}) = 0

mmap2(NULL, 78351, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7717000

close(3)                                = 0

access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)

open("/lib/i386-linux-gnu/tls/i686/sse2/cmov/libsocketcomm.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

stat64("/lib/i386-linux-gnu/tls/i686/sse2/cmov", 0xbfd79b50) = -1 ENOENT (No such file or directory)

open("/lib/i386-linux-gnu/tls/i686/sse2/libsocketcomm.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

stat64("/lib/i386-linux-gnu/tls/i686/sse2", 0xbfd79b50) = -1 ENOENT (No such file or directory)

open("/lib/i386-linux-gnu/tls/i686/cmov/libsocketcomm.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

stat64("/lib/i386-linux-gnu/tls/i686/cmov", 0xbfd79b50) = -1 ENOENT (No such file or directory)

………

stat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=36864, ...}) = 0

writev(2, [{"./mytest", 8}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libsocketcomm.so", 16}, {": ", 2}, {"cannot open shared object file", 30}, {": ", 2}, {"No such file or directory", 25}, {"\n", 1}], 10./mytest: error while loading shared libraries: libsocketcomm.so: cannot open shared object file: No such file or directory

) = 124

exit_group(127) 

现在你可以发现是缺少相应的库而退出程序了。而且这个命令还是按照调用的顺序来进行列出相应的库文件的,非常好用。其中有些参数非常有用,比如-e,可以用来显示调用某个函数的模块:

Strace –o 1.txt –e  函数名  ./mytest

-e expr 指定一个表达式,用来控制如何跟踪.格式如下:

 

[qualifier=][!]value1[,value2]...

 

qualifier 只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier trace.感叹号是否定符号.例如-eopen等价于 -e trace=open,表示只跟踪open调用. -etrace!=open表示跟踪除了open以外的其它调用.有两个特殊的符号 all none. 注意有些shell使用!来执行历史记录里的命令,所以要使用\\.

 

-e trace=set 只跟踪指定的系统调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.

-e trace=file 只跟踪有关文件操作的系统调用.

-e trace=process 只跟踪有关进程控制的系统调用.

-e trace=network 跟踪与网络有关的所有系统调用.

-e strace=signal 跟踪所有与系统信号有关的系统调用.

-e trace=ipc 跟踪所有与进程通讯有关的系统调用.

-e abbrev=set 设定strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.

-e raw=set 将指定的系统调用的参数以十六进制显示.

-e signal=set 指定跟踪的系统信号.默认为all. signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.

-e read=set 输出从指定文件中读出的数据.例如-e read=3,5

-e write=set 输出写入到指定文件中的数据.

-o filename strace的输出写入文件filename

-p pid 跟踪指定的进程pid.

-s strsize 指定输出的字符串的最大长度.默认为32.文件名一直全部输出.

-u username username UIDGID执行被跟踪的命令.

看一个例子:

strace还可以通过进程ID来进行对进程的绑定。这样在调试网络程序或者其它僵死程序是特别有用。以下是我绑定在我ubuntu上的apt程序进输出的结果:

 

Process 9012 attached - interrupt to quit

select(4, NULL, [3], NULL, {101, 527785}) = 1 (out [3], left {98, 971795})

getsockopt(3, SOL_SOCKET, SO_ERROR, [110], [4]) = 0

open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

 

当然strace可以也可用来统计系统调用的次数和时间这样可以帮助你分析程序的瓶颈。

补充一点:2015-08-25

NDK编译的SO中,直接使用NM命令总报没有符号导出。与原来在LINUX直接编译出来的还是有区别的。然后在网上查找了一下,发现了两个方法:

nm -D 7z.so

objdump -tT 7z.so

  评论这张
 
阅读(733)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017