成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

sewerganger / 1396人閱讀

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

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

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

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

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

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

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

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

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

1 搭建 debug 環(huán)境

1、下載編譯文件
在 linux 上,下載源碼文件,編譯,使用 gdb(cgdb) 進行 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、開啟 debug

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

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

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

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

設(shè)置好斷點,下一步就是啟動服務(wù):

// 啟動服務(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) {

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

(gdb) layout src

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

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

2 初始化服務(wù)

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

(gdb) s

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

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

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

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

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

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

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

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

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

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