Redisソース学習-8-Redisソースネットワーク部分の簡単な分析
13721 ワード
main関数フロー
文書ディレクトリ main関数フロー 0. 前言 1. 簡易ソース分析 1.1小結
0.はじめに
次に、コード、または関数呼び出しスタックについて、見てみましょう.Redisはどうやって作ったのですか.
1.簡単なソース分析
現在、私たちはまずいくつかのビジネス上のコードを除いて、ネットワークに関するコードだけを見ています.
簡単に説明します. Reactor の設定 socket,bink,listen を完了は、原子炉注入の初期イベントに相当するaccepttTcpHandlerを登録する.接続すると原子炉が作動しますaccepttTcpHandlerの登録には、必ず1についてがあると推測できる.新しい接続が来る処理.
新しい接続が来ると、acceptCommonHandlerは新しい接続を処理します.
クライアントからのコマンドを処理するためにreadQueryFromClientが新しい接続に登録されていることがわかります.残りはプロトコルを解析し、コマンドを処理することです.そして命令の結果を得る.対応するコマンドに従って、異なる処理関数をコールバックします.
実際には、コマンドテーブルの大きなテーブルでコマンドを検索します.
1.1まとめ
上記のフロー処理がわかっていれば、Redisのフローがわかりやすくなります.ではRedisのネットワークプログラミング部分は基本的にこれで終わります.私のゼロからRedisを書くことができて、どのようにC++を使って自分のRedisネットワークの部分を書くかについて話します.
文書ディレクトリ
0.はじめに
次に、コード、または関数呼び出しスタックについて、見てみましょう.Redisはどうやって作ったのですか.
1.簡単なソース分析
現在、私たちはまずいくつかのビジネス上のコードを除いて、ネットワークに関するコードだけを見ています.
// redis.c
int main(int argc, char **argv) {
//
// ,
initServerConfig();
//
if (server.daemonize) daemonize();
//
initServer();
...
}
// initServer
void initServer() {
// EventLoop
server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR);
//
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
// TCP ,
if (server.port != 0 &&
listenToPort(server.port,server.ipfd,&server.ipfd_count) == REDIS_ERR)
exit(1);
// TCP (accept)
// connect()
for (j = 0; j < server.ipfd_count; j++) {
if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
acceptTcpHandler,NULL) == AE_ERR)
{
redisPanic(
"Unrecoverable error creating server.ipfd file event.");
}
}
}
簡単に説明します.
void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
while(max--) {
// accept
cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
if (cfd == ANET_ERR) {
if (errno != EWOULDBLOCK)
redisLog(REDIS_WARNING,
"Accepting client connection: %s", server.neterr);
return;
}
redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport);
// (redisClient)
acceptCommonHandler(cfd,0);
}
}
新しい接続が来ると、acceptCommonHandlerは新しい接続を処理します.
static void acceptCommonHandler(int fd, int flags) {
//
redisClient *c;
if ((c = createClient(fd)) == NULL) {
redisLog(REDIS_WARNING,
"Error registering fd event for the new client: %s (fd=%d)",
strerror(errno),fd);
close(fd); /* May be already closed, just ignore errors */
return;
}
}
redisClient *createClient(int fd) {
if (aeCreateFileEvent(server.el,fd,AE_READABLE,
readQueryFromClient, c) == AE_ERR)
{
...
}
}
クライアントからのコマンドを処理するためにreadQueryFromClientが新しい接続に登録されていることがわかります.残りはプロトコルを解析し、コマンドを処理することです.そして命令の結果を得る.対応するコマンドに従って、異なる処理関数をコールバックします.
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
processInputBuffer(c);
}
実際には、コマンドテーブルの大きなテーブルでコマンドを検索します.
1.1まとめ
上記のフロー処理がわかっていれば、Redisのフローがわかりやすくなります.ではRedisのネットワークプログラミング部分は基本的にこれで終わります.私のゼロからRedisを書くことができて、どのようにC++を使って自分のRedisネットワークの部分を書くかについて話します.