成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

跟著大彬讀源碼 - Redis 1 - 啟動(dòng)服務(wù),程序都干了什么?

sewerganger / 1313人閱讀

摘要:此時(shí)服務(wù)器處于休眠狀態(tài),并使用進(jìn)行事件輪詢,等待監(jiān)聽(tīng)事件的發(fā)生。繼續(xù)執(zhí)行被調(diào)試程序,直至下一個(gè)斷點(diǎn)或程序結(jié)束縮寫(xiě)。服務(wù)啟動(dòng)包括初始化基礎(chǔ)配置數(shù)據(jù)結(jié)構(gòu)對(duì)外提供服務(wù)的準(zhǔn)備工作還原數(shù)據(jù)庫(kù)執(zhí)行事件循環(huán)等。

一直很羨慕那些能讀 Redis 源碼的童鞋,也一直想自己解讀一遍,但迫于 C 大魔王的壓力,解讀日期遙遙無(wú)期。

相信很多小伙伴應(yīng)該也都對(duì)或曾對(duì)源碼感興趣,但一來(lái)覺(jué)得自己不會(huì) C 語(yǔ)言,二來(lái)也不知從何入手,結(jié)果就和博主一樣,一拖再拖。

但正所謂,種一棵樹(shù)的最好時(shí)間是十年前,其次就是現(xiàn)在。如果你真的想了解 Redis 源碼,又有緣看到了這系列博文,何不跟著博主一起解讀 Redis 源碼,做個(gè)同行人呢?接下來(lái),就讓我們一起走入 Redis 的源碼世界吧。

決定要讀了,下一步就是如何讀。從 github 上克隆下來(lái)源碼,一看 src 目錄,望天,104 個(gè)文件,我該從哪個(gè)文件開(kāi)始呢?一個(gè)個(gè)文件看?不行不行,這樣對(duì)我毫無(wú)誘惑力,沒(méi)有誘惑力,怎么能戰(zhàn)勝游戲、小說(shuō)對(duì)我的吸引呢?苦苦思考,不得其解。然后突然想起來(lái) HTTP 協(xié)議的那個(gè)經(jīng)典面試題:從瀏覽器輸入網(wǎng)址,到頁(yè)面展示,這個(gè)過(guò)程發(fā)生了什么?

把這個(gè)面試題換成 Redis:輸入開(kāi)啟 Redis 服務(wù)的命令,回車,到成功啟動(dòng) Redis 服務(wù),這個(gè)過(guò)程發(fā)生了什么?

很好,這個(gè)問(wèn)題成功吸引到我了。就讓我們從源碼中找出這個(gè)問(wèn)題的答案吧。后續(xù)的所有文章我們都嘗試通過(guò)提出問(wèn)題,解答問(wèn)題的步驟,來(lái)深入了解 Redis。

要了解 Redis 命令的執(zhí)行過(guò)程,首先要安裝 Redis 服務(wù),搭建 debug 環(huán)境。如果我們能一行行的看到命令在代碼中的執(zhí)行過(guò)程,解讀源碼也就沒(méi)任何阻礙了。

后續(xù)所有文章均基于 redis3.2.13 版本。

1 搭建 debug 環(huán)境

1、下載編譯文件
在 linux 上,下載源碼文件,編譯,使用 gdb(cgdb) 進(jìn)行 debug。

# bash
wget https://github.com/antirez/redis/archive/3.2.13.tar.gz
tar -zxvf 3.2.13.tar.gz
mv redis-3.2.13 /opt/
cd redis-3.2.13
make                 # 編譯文件,得到可執(zhí)行文件 redis-server、redis-cli 等

2、開(kāi)啟 debug

# bash
gdb src/redis-server # 在 redis 安裝目錄,進(jìn)入 gdb 調(diào)試環(huán)境

按我們平時(shí)調(diào)試的習(xí)慣,找到一個(gè)函數(shù)設(shè)置斷點(diǎn),然后一步步運(yùn)行調(diào)試。對(duì)于 Redis 也一樣,我們找到 server.c 文件,服務(wù)器運(yùn)行的 main 函數(shù)就在此文件中。我們對(duì) main 函數(shù)設(shè)置斷點(diǎn):

# gdb
(gdb) b main
Breakpoint 1 at 0x42ed05: file server.c, line 3962.

頁(yè)面會(huì)提示我們?cè)?server.c 文件的 3962 行設(shè)置了斷點(diǎn),也就是我們指定的 main 函數(shù)的位置。

設(shè)置好斷點(diǎn),下一步就是啟動(dòng)服務(wù):

// 啟動(dòng)服務(wù)
(gdb) r ./redis.conf
Starting program: /opt/redis-3.2.13/src/redis-server ./redis.conf
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=2, argv=0x7fffffffe5a8) at server.c:3962
3962    int main(int argc, char **argv) {

通過(guò)頁(yè)面輸出信息,我們會(huì)發(fā)現(xiàn)程序已經(jīng)運(yùn)行到我們?cè)O(shè)置的斷點(diǎn)了。但是我們看不到運(yùn)行處的代碼,這可不行,看不到源碼的調(diào)試,沒(méi)法接受使用以下命令”召喚“源碼:

(gdb) layout src

出現(xiàn)下圖所示的界面:

到了這一步,我們已經(jīng)正式開(kāi)始踏上 Redis 源碼解讀之路了。

2 初始化服務(wù)

繼續(xù)往下走,使用 n 命令,執(zhí)行下一步,然后不斷回車、回車、回車,好像每一行都看不懂什么意思。不管了,繼續(xù)走。咦,好像發(fā)現(xiàn)個(gè)能看懂的 initServerConfig()。沒(méi)看錯(cuò)的話,這個(gè)應(yīng)該是初始化服務(wù)器配置的,讓我們進(jìn)到這個(gè)函數(shù)里確認(rèn)下:

(gdb) s

回車,走你。然后我們就看到了下面這個(gè)界面:

提示我們進(jìn)入了 server.c 1464 行的 initServerConfig 函數(shù)中。 n 命令,繼續(xù)走。我們會(huì)發(fā)現(xiàn)在這個(gè)函數(shù)里對(duì)服務(wù)器的各種基礎(chǔ)參數(shù)進(jìn)行初始化。這里的參數(shù)詳見(jiàn) server.h/redisServer 結(jié)構(gòu)體。

回到 main 函數(shù)后,我們繼續(xù)前進(jìn),還會(huì)發(fā)現(xiàn)一個(gè) initServer() 的函數(shù)。這個(gè)函數(shù)是進(jìn)行驅(qū)動(dòng)事件的注冊(cè),以及綁定回調(diào)函數(shù)等。

繼續(xù)走,直到執(zhí)行 aeMain(),如下圖:

程序執(zhí)行到 4133 行時(shí),Redis 服務(wù)已成功開(kāi)啟了。此時(shí)服務(wù)器處于休眠狀態(tài),并使用 aeMain() 進(jìn)行事件輪詢,等待監(jiān)聽(tīng)事件的發(fā)生。

上述整個(gè)過(guò)程,我們只是跟著程序的運(yùn)行,大概看了一遍執(zhí)行流程。下面,我們來(lái)詳細(xì)解讀上面敘述的關(guān)鍵步驟:初始化基礎(chǔ)配置初始化服務(wù)器數(shù)據(jù)結(jié)構(gòu)。

3 初始化詳細(xì)解讀 3.1 初始化基礎(chǔ)配置

初始化服務(wù)器的第一步就是創(chuàng)建一個(gè) `redisServer 類型的實(shí)例變量 server 作為服務(wù)器的狀態(tài),并為結(jié)構(gòu)中的各個(gè)屬性設(shè)置默認(rèn)值。

void initServerConfig(void) {
    int j;
    // 設(shè)置服務(wù)器運(yùn)行 ID
    getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);

    // 為運(yùn)行 ID 加上結(jié)尾字符
    server.runid[CONFIG_RUN_ID_SIZE] = "