通過gdb來除錯和觀察redis原始碼的執行

2021-08-27 10:53:25 字數 2802 閱讀 5851

本文介紹如何通過gdb來除錯redis的源**。相對於只是檢視原始碼,通過gdb還能夠在實際場景中觀察**如何執行,記憶體如何變化,這對於理解redis-server的執行機制非常有必要。

在進行redis-server一般命令的執行機制除錯時,不需要你精通c/c++程式設計,只需要知道gdb的一些基本命令就可以了。

通過gdb對redis-server進行除錯時,需要知道一些基本的gdb命令。比如說,如何打斷點,如何列印結構體的內容,如何跟蹤子程序的執行等等。本節介紹一些基本的gdb命令,通過這些命令就可以進入redis的世界了。

$ gdb ./src/redis-server

(gdb)

命令名功能r

執行剛才載入的二進位制程式,可以指定引數

b打斷點,後面的引數可以是函式,或行數

n單步執行,但不進入函式中

s單步執行,進入呼叫函式

bt檢視目前的呼叫堆疊(很有用,可以檢視函式的呼叫棧,和目前執行的位置)

l檢視**,引數可以是函式名,或行數

p列印變數或結構體的值

其他命令可以檢視gdb手冊。

cd redis-4.0.9

make

編譯好的二進位制在src下,還要注意,在redis-4.0.9目錄下有乙個redis.conf檔案,這是執行redis-server時的配置檔案。

編譯完成後,在src下,應該還有幾個其他編譯好的可執行檔案:

redis-server: redis服務的主二進位制**

redis-cli : redis命令列客戶端

redis-benchmark

redis-sentinel

...

本文介紹中,我們要用到的是兩個 redis-server和redis-cli

好了,編譯好**後,我們開始除錯redis-server了

$ gdb src/redis-server 

(gdb)

要檢視set命令的執行過程,首先要對執行set命令的函式入口打上斷點。然後進入該處理函式,單步執行。在server.c**中,有乙個命令處理的列表函式,如下:

struct rediscommand rediscommandtable = ,,,

,,

......

從以上**我們看到set命令的實現函式是setcommand,我們可以在該函式的入口處打上斷點:

// 打上斷點

(gdb) b setcommand

// 執行redis-server

(gdb) r ./redis.conf

此時,gdb會阻塞在redis-server的等待連線的地方,因為沒有redis客戶端連線服務端,此時我們需要啟動redis-cli,並傳送set命令。

開乙個新的終端,進入剛才編譯redis的目錄,並啟動redis-cli。

cd redis-4.0.9/src

$ ./redis-cli

127.0.0.1:6379> set k1 "v123"

(gdb) bt

#0 setcommand (c=0x102016000) at t_string.c:102

#10x000000010000cd53 in call (c=0x102016000, flags=15) at server.c:2229

#20x000000010000d61e in processcommand (c=0x102016000) at server.c:2510

#30x000000010001dd76 in processinputbuffer (c=0x5b91a431) at networking.c:1354

#40x00000001000051ee in aeprocessevents (eventloop=0x1005289b0, flags=11) at ae.c:440

#50x000000010000552b in aemain (eventloop=0x5b91a431) at ae.c:498

#60x0000000100010680 in main (argc=1, argv=0x0) at server.c:3894

進入該函式,並單步執行:

(gdb) n

138 c->argv[2] = tryobjectencoding(c->argv[2]); //為了節約記憶體:對string的value進行編碼

若想進入函式內部,直接通過s命令:

(gdb) s

tryobjectencoding (o=0x100306600) at object.c:384

384 serverassertwithinfo(null,o,o->type == obj_string);

列印變數的值:

(gdb) p o

$1 = (robj *) 0x100306600

// o是指標

// 通過以下命令列印指標的內容

(gdb) p *o

$2 =

(gdb) p o->type

若要直到命令處理的全過程,可以processcommand函式打上斷點。然後,和上面介紹的一樣單步執行。

本文描述了如何通過gdb對redis-server進行除錯,並對redis-server的內部執行進行觀察。但本文並沒有介紹更加複雜的gdb的除錯技巧,比如多程序的除錯。

GDB來除錯IPHONE步驟

iphone手機必須越獄 安裝以下外掛程式是必需的 openssh,作為ssh服務端 gnu debugger gdb除錯工具 在這個源中cydia.radare.org,版本為1708,低版本不支援ios4.3 adv cmds ps命令可以檢視程序資訊 darwin cc tools otool...

通過 GDB 除錯理解 GOT PLT

關於 linux 中 elf 檔案格式可參考詳細文件 elf format 本文僅記錄筆者理解got plt的過程。got global offset table 全域性偏移表用於記錄在 elf 檔案中所用到的共享庫中符號的絕對位址。在程式剛開始執行時,got 表項是空的,當符號第一次被呼叫時會動態...

通過GDB除錯理解指標

源 include intmain 編譯上面的 之後進行除錯。在初始化之前,a pon ppon的值各為 可以使用info locals命令進行檢視區域性變數 0x0執行結束退出main之前,a pon ppon的值各為 a 0xapon 0x7ffeefbff94c ppon 0x7ffeefbf...