linux常用命令--开发调试篇
前言
Linux常用命令中有一些命令可以在開發(fā)或調試過程中起到很好的幫助作用,有些可以幫助了解或優(yōu)化我們的程序,有些可以幫我們定位疑難問題。本文將簡單介紹一下這些命令。
轉自:https://www.yanbinghu.com/2018/09/26/61877.html
示例程序
我們用一個小程序,來幫助后面我們對這些命令的描述,程序清單cmdTest.c如下:
#include<stdio.h> 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函數(shù)中調用test,計算a/b的值,其中b的值為0,因此程序由于除0錯誤異常終止。
常用開發(fā)調試命令
1 查看文件基本信息—file
file cmdTest輸出:
cmdTest: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a1bd4a7dd456246a029c0f5dfc763042b8d2c68e, with debug_info, not stripped通過file命令可以看到cmdTest的類型為elf,是64位、運行于x86-64的程序,not striped表明elf文件中還保留著符號信息以及調試信息等不影響程序運行的內容。
2 查看程序依賴庫—ldd
ldd cmdTest輸出:
linux-vdso.so.1 (0x00007fffa5be0000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3185bf0000)/lib64/ld-linux-x86-64.so.2 (0x00007f31861e3000)我們可以看到cmdTest依賴了libc.so等庫。
3 查看函數(shù)或者全局變量是否存在于elf文件中—nm
nm命令用于查看elf文件的符號信息。文件編譯出來之后,我們可能不知道新增加的函數(shù)或者全局變量是否已經成功編譯進去。這時候,我們可以使用nm命令來查看。
例如,查看前面所提到的elf文件有沒有test函數(shù),可以用命令:
輸出:
000000000040052d T test按照地址順序列出符號信息:
nm -n cmdTest輸出:
w __cxa_finalize@@GLIBC_2.2.5w __gmon_start__w _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTableU __libc_start_main@@GLIBC_2.2.5U printf@@GLIBC_2.2.5 00000000000004f0 T _init 0000000000000540 T _start 0000000000000570 t deregister_tm_clones 00000000000005b0 t register_tm_clones 0000000000000600 t __do_global_dtors_aux 0000000000000640 t frame_dummy 000000000000064a T test 000000000000065d T main 00000000000006b0 T __libc_csu_init 0000000000000720 T __libc_csu_fini 0000000000000724 T _fini 0000000000000730 R _IO_stdin_used 0000000000000740 r __GNU_EH_FRAME_HDR 00000000000008ac r __FRAME_END__ 0000000000200db8 t __frame_dummy_init_array_entry 0000000000200db8 t __init_array_start 0000000000200dc0 t __do_global_dtors_aux_fini_array_entry 0000000000200dc0 t __init_array_end 0000000000200dc8 d _DYNAMIC 0000000000200fb8 d _GLOBAL_OFFSET_TABLE_ 0000000000201000 D __data_start 0000000000201000 W data_start 0000000000201008 D __dso_handle 0000000000201010 B __bss_start 0000000000201010 b completed.7698 0000000000201010 D _edata 0000000000201010 D __TMC_END__ 0000000000201018 B _end可以看到test函數(shù)的開始地址為000000000000064a,結束地址為000000000000065d。
4 打印elf文件中的可打印字符串—strings
例如你在代碼中存儲了一個版本號信息,那么即使編譯成elf文件后,仍然可以通過strings搜索其中的字符串甚至可以搜索某個.c文件是否編譯在其中:
strings elfFile| grep "someString"5 查看文件段大小—size
可以通過size命令查看各段大小:
size cmdTest輸出:
text data bss dec hex filename1619 600 8 2227 8b3 cmdTesttext段:正文段字節(jié)數(shù)大小
data段:包含靜態(tài)變量和已經初始化的全局變量的數(shù)據段字節(jié)數(shù)大小
bss段:存放程序中未初始化的全局變量的字節(jié)數(shù)大小
當我們知道各個段的大小之后,如果有減小程序大小的需求,就可以有針對性的對elf文件進行優(yōu)化處理。
6 為elf文件”瘦身“—strip
strip用于去掉elf文件中所有的符號信息:
ls -al cmdTest -rwxr-xr-x 1 hyb root 9792 Sep 25 20:30 cmdTest #總大小為9792字節(jié)strip cmdTestls -al cmdTest -rwxr-xr-x 1 hyb root 6248 Sep 25 20:35 cmdTest#strip之后大小為6248字節(jié)可以看到,“瘦身”之后,大小減少將近三分之一。但是要特別注意的是,“瘦身”之后的elf文件由于沒有了符號信息,許多調試命令將無法正常使用,出現(xiàn)core dump時,問題也較難定位,因此只建議在正式發(fā)布時對其進行“瘦身”。
7 查看elf文件信息—readelf
readelf用于查看elf文件信息,它可以查看各段信息,符號信息等,下面的例子是查看elf文件頭信息:
readelf -h cmdTest輸出:
ELF Header:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: DYN (Shared object file)Machine: Advanced Micro Devices X86-64Version: 0x1Entry point address: 0x540Start of program headers: 64 (bytes into file)Start of section headers: 8808 (bytes into file)Flags: 0x0Size of this header: 64 (bytes)Size of program headers: 56 (bytes)Number of program headers: 9Size of section headers: 64 (bytes)Number of section headers: 34Section header string table index: 33從elf頭信息中,我們可以知道該elf是64位可執(zhí)行文件,運行在x86-64中,且字節(jié)序為小端序。另外,我們還注意到它的入口地址是0x400440(_start),而不是400540(main)。也就是說,我們的程序運行并非從main開始。
8 反匯編指定函數(shù)—objdump
objdump用于展示elf文件信息,功能較多,在此不逐一介紹。有時候我們需要反匯編來定位一些問題,可以使用命令:
objdump -d cmdTest #反匯編整個cmdTest程序但是如果程序較大,那么反匯編時間將會變長,而且反匯編文件也會很大。如果我們已經知道了問題在某個函數(shù),只想反匯編某一個函數(shù),怎么處理呢?
我們可以利用前面介紹的nm命令獲取到函數(shù)test的地址,然后使用下面的方式反匯編:
9 端口占用情況查看—netstat
我們可能常常會遇到進程第一次啟動后,再次啟動會出現(xiàn)端口綁定失敗的問題,我們可以通過netstat命令查看端口占用情況:
netstat -anp|grep 端口號10 進程狀態(tài)查看—ps&top
ps命令用于顯示當前進程的狀態(tài),類似于 windows 的任務管理器。
top命令實時顯示當前進程狀態(tài),最活躍的進程顯示在最頂部。
11 core dump文件生成配置—ulimit -c
有時候我們的程序core dump了卻沒有生成core文件,很可能是我們設置的問題:
ulimit -c #查看core文件配置,如果結果為0,程序core dump時將不會生成core文件 ulimit -c unlimited #不限制core文件生成大小 ulimit -c 10 #設置最大生成大小為10kb12 調試神器—gdb
gdb是一個強大的調試工具,但這里僅介紹兩個簡單使用示例。
有時候程序可能已經正在運行,但是又不能終止它,這時候仍然可以使用gdb調試正在運行的進程:
有時候程序可能core dump了,但是系統(tǒng)還留給了我們一個禮物—core文件。
在core文件生成配置完成之后,運行cmdTest程序,產生core文件。我們可以用下面的方法通過core文件定位出錯位置:
輸入bt后,就可以看到調用棧了,出錯位置在test函數(shù),cmdTest.c的第4行。
13 定位crash問題—addr2line
有時候程序崩潰了但不幸沒有生成core文件,是不是就完全沒有辦法了呢?還是cmdTest的例子。運行完cmdTest之后,我們通過dmesg命令可以獲取到以下內容
[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常用命令--开发调试篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win7光盘放进电脑没反应怎么办 解决w
- 下一篇: 计算机主板怎么看 如何查看计算机主板信息