linux常用命令--开发调试篇
文章图片
前言
Linux常用命令中有一些命令可以在开发或调试过程中起到很好的帮助作用,有些可以帮助了解或优化我们的程序,有些可以帮我们定位疑难问题。本文将简单介绍一下这些命令。
示例程序
【linux常用命令--开发调试篇】我们用一个小程序,来帮助后面我们对这些命令的描述,程序清单cmdTest.c如下:
#include
int test(int a,int b)
{
return a/b;
}
int main(int argc, char *argv[])
{
int a = 10;
int b = 0;
printf("a=%d,b=%d\n",a,b);
test(a,b);
return 0;
}
编译获得elf文件cmdTest并运行:
gcc -g -o cmdTest cmdTest.c
./cmdTest
a=10,b=0
Floating point exception (core dumped)
程序内容是在main函数中调用test,计算a/b的值,其中b的值为0,因此程序由于除0错误异常终止。
- 查看文件基本信息-->file
file cmdTest
cmdTest: ELF 64-bit LSBexecutable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=448e1c34b4c548120e2c04f6a2bfce4e6d2281a3, not stripped
通过file命令可以看到cmdTest的类型为elf,是64位、运行于x86-64的程序,not striped表明elf文件中还保留着符号信息以及调试信息等不影响程序运行的内容。
- 查看程序依赖库-->ldd
ldd cmdTest
linux-vdso.so.1 =>(0x00007ffc8e548000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0621931000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0621cf6000)
我们可以看到cmdTest依赖了libc.so等库。
- 查看函数或者全局变量是否存在于elf文件中-->nm
例如,查看前面所提到的elf文件有没有test函数,可以用命令:
nm cmdTest | grep test
000000000040052d T test#打印结果
按照地址顺序列出符号信息:
nm -n cmdTest
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
00000000004003e0 T _init
0000000000400440 T _start
0000000000400470 t deregister_tm_clones
00000000004004a0 t register_tm_clones
00000000004004e0 t __do_global_dtors_aux
0000000000400500 t frame_dummy
000000000040052d T test
0000000000400540 T main
0000000000400590 T __libc_csu_init
0000000000400600 T __libc_csu_fini
(列出部分内容)
可以看到test函数的开始地址为0x000000000040052d,结束地址为0x0000000000400540。
- 打印elf文件中的可打印字符串-->strings
strings elfFile | grep "someString"
- 查看文件段大小-->size
size cmdTest
textdatabssdechexfilename
13195608188775fcmdTest
text段:正文段字节数大小
data段:包含静态变量和已经初始化的全局变量的数据段字节数大小
bss段:存放程序中未初始化的全局变量的字节数大小
当我们知道各个段的大小之后,如果有减小程序大小的需求,就可以有针对性的对elf文件进行优化处理。
- 为elf文件”瘦身“-->strip
ls -al cmdTest
-rwxr-xr-x 1 hyb root 9792 Sep 25 20:30 cmdTest #总大小为9792字节strip cmdTest
ls -al cmdTest
-rwxr-xr-x 1 hyb root 6248 Sep 25 20:35 cmdTest#strip之后大小为6248字节
可以看到,“瘦身”之后,大小减少将近三分之一。但是要特别注意的是,“瘦身”之后的elf文件由于没有了符号信息,许多调试命令将无法正常使用,出现core dump时,问题也较难定位,因此只建议在正式发布时对其进行“瘦身”。
- 查看elf文件信息-->readelf
readelf -h cmdTest
Magic:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00#elf文件魔数字
Class:ELF64#64位 elf文件
Data:2's complement, little endian#字节序为小端序
Version:1 (current)
OS/ABI:UNIX - System V #
ABI Version:0
Type:EXEC (Executable file)#目标文件类型
Machine:Advanced Micro Devices X86-64 #目标处理器体系
Version:0x1
Entry point address:0x400440#入口地址
Start of program headers:64 (bytes into file)
Start of section headers:4456 (bytes into file)
Flags:0x0
Size of this header:64 (bytes)
Size of program headers:56 (bytes)
Number of program headers:9
Size of section headers:64 (bytes)
Number of section headers:28
Section header string table index: 27
从elf头信息中,我们可以知道该elf是64位可执行文件,运行在x86-64中,且字节序为小端序。另外,我们还注意到它的入口地址是0x400440 (_start),而不是400540 (main)。也就是说,我们的程序运行并非从main开始。
- 反汇编指定函数-->objdump
objdump -d cmdTest #反汇编整个cmdTest程序
但是如果程序较大,那么反汇编时间将会变长,而且反汇编文件也会很大。如果我们已经知道了问题在某个函数,只想反汇编某一个函数,怎么处理呢?
我们可以利用前面介绍的nm命令获取到函数test的地址,然后使用下面的方式反汇编:
objdump -d cmdTest --start-address=0x40052d --stop-address=0x400540 ##反汇编指定地址区间
- 端口占用情况查看-->netstat
netstat -anp | grep 端口号
- 进程状态查看-->ps或top
top命令实时显示当前进程状态,最活跃的进程显示在最顶部。
- -core dump文件生成配置-->ulimit -c*
ulimit -c #查看core文件配置,如果结果为0,程序core dump时将不会生成core文件
ulimit -c unlimited #不限制core文件生成大小
ulimit -c 10 #设置最大生成大小为10kb
调试神器-->gdb gdb是一个强大的调试工具,但这里仅介绍两个简单使用示例。有时候程序可能已经正在运行,但是又不能终止它,这时候仍然可以使用gdb调试正在运行的进程:
gdb processFile PID #processFile为进程文件,pid为进程id,可通过ps命令查找到
有时候程序可能core dump了,但是系统还留给了我们一个礼物--core文件。在core文件生成配置完成之后,运行cmdTest程序,产生core文件。我们可以用下面的方法通过core文件定位出错位置:
gdb cmdTest core #cmdTest为进程文件,core为生成的core文件
Core was generated by `./cmdTest'.
Program terminated with signal SIGFPE, Arithmetic exception.
#00x00000000004004fb in test (a=10, b=0) at cmdTest.c:4
4return a/b;
(gdb)bt
#00x00000000004004fb in test (a=10, b=0) at cmdTest.c:4
#10x000000000040052c in main (argc=1, argv=0x7ffca9536d38) at cmdTest.c:10
(gdb)
输入bt后,就可以看到调用栈了,出错位置在test函数,cmdTest.c的第4行。
- 定位crash问题-->addr2line
[27153070.538380] traps: cmdTest[2836] trap divide error ip:40053b sp:7ffc230d9280 error:0 in cmdTest[400000+1000]
该信息记录了cmdTest运行出错的基本原因(divide error)和出错位置(40053b),我们使用addr2line命令获取出错具体行号:
addr2line -e cmdTest 40053b
/home/hyb/practice/cmdTest.c:4
可以看到addr2line命令将地址(40053b)翻译成了文件名(cmdTest.c)和行号(4),确定了出错位置。
总结 本文对以上命令仅介绍其经典使用,这些命令都还有其他一些有帮助的用法,但由于篇幅有限,不在此介绍,更多使用方法可以通过man 命令名的方式去了解。
=========我是华丽的分割线=========
更多知识:
点击关注专题:嵌入式Linux&ARM
或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1
或扫描二维码:
文章图片
文章参考微信公众号[编程珠玑]
推荐阅读
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- Linux下面如何查看tomcat已经使用多少线程
- 数组常用方法一
- Beego打包部署到Linux
- 你命令我爱你吧(原创)
- Linux|109 个实用 shell 脚本
- linux定时任务contab
- 芯灵思SinlinxA33开发板Linux内核定时器编程
- 常用git命令总结
- java|java 常用知识点链接