スカイネットのソースコード解析

スカイネットのソースコード解析

序文

この記事のバージョンは Skynet v1.4.0 です。Skynet をコンパイルするために避けられないのは make です。

この記事では、特に make の実装について見ていきます。

make については、 Ruan Yifeng のブログを参照してください

また、この記事ではトップレベルの Makefile についてのみ説明し、サブディレクトリ内の Makefile については分析しません。

付録は GCC のいくつかのパラメータです。

文章

skynet ディレクトリで実行すると、実際にはそのディレクトリ内のコマンドがmake linux実行されます。Makefileファイルの最初の行には次のステートメントがあります。

include platform.mk

プラットフォーム.mk

ロジックはおおよそ次のとおりです。

  1. 正しいプラットフォームが渡されたかどうかを確認しますlinux freebsd macosxそうでない場合は、エラー メッセージを表示して終了します。

    wyw@DESKTOP-GJ20UDC:~/skynet$ make
    make none
    make[1]: Entering directory '/home/wyw/skynet'
    Please do 'make PLATFORM' where PLATFORM is one of these:
       linux freebsd macosx
    make[1]: Leaving directory '/home/wyw/skynet'
    

    間違ったプラットフォームが渡された場合、同様の出力が表示されます。

    wyw@DESKTOP-GJ20UDC:~/skynet$ make l
    make: *** No rule to make target 'l'.  Stop.
    
  2. プラットフォームごとに異なる変数が設定されており、ここで設定した変数が Makefile で使用されます。たとえばmake linux最後のコマンドまでの実行は次のようになります。

    # make all PLAT=linux SKYNET_LIBS="-lpthread -lm -ldl -lrt" SHARED="-fPIC --shared" EXPORT="-Wl,-E" MALLOC_STATICLIB="" SKYNET_DEFINES=""
    $(MAKE) all PLAT=$@ SKYNET_LIBS="$(SKYNET_LIBS)" SHARED="$(SHARED)" EXPORT="$(EXPORT)" MALLOC_STATICLIB="$(MALLOC_STATICLIB)" SKYNET_DEFINES="$(SKYNET_DEFINES)"
    

メイクファイル

Makefile に戻ると、いくつかのプラットフォーム関連の値が include の後に設定されます。そして実行されるmake all

ロジックはおおよそ次のとおりです。

  1. ジェマロックを生成する
  2. Skynet関連のパーツを生成する

ジェマロック

Jemalloc はメモリ アロケータであり、他のメモリ アロケータと比較した最大の利点は、マルチスレッド環境での高いパフォーマンスとメモリの断片化の軽減にあります。

Skynet プロジェクトの README.md を読みます。次のような一文があります。

Linux の場合は、最初に jemalloc 用に autoconf をインストールします。

理由は後で明らかになるので、まず Makefile を分析しましょう。

開始ステートメント:

# 定义变量MALLOC_STATICLIB
JEMALLOC_STATICLIB := 3rd/jemalloc/lib/libjemalloc_pic.a
MALLOC_STATICLIB := $(JEMALLOC_STATICLIB)

all : jemalloc
# 声明伪目标 jemalloc update3rd
.PHONY : jemalloc update3rd
# 伪目标前提是 $(MALLOC_STATICLIB)
jemalloc : $(MALLOC_STATICLIB)
# 前提是先生成 3rd/jemalloc/Makefile,后执行命令cd 3rd/jemalloc && $(MAKE) CC=$(CC)
# 这一步的make 中需要用到 AUTOCONF := /usr/bin/autoconf
$(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile
	cd 3rd/jemalloc && $(MAKE) CC=$(CC) 
# 生成3rd/jemalloc/Makefile  order-only先决条件 从git拉取模块

3rd/jemalloc/Makefile : | 3rd/jemalloc/autogen.sh
	# 执行autogen.sh
	cd 3rd/jemalloc && ./autogen.sh --with-jemalloc-prefix=je_ --enable-prof

3rd/jemalloc/autogen.sh :
	git submodule update --init

スカイネット

この部分にはさらに多くの内容があり、最初にいくつかの変数を定義します。

CSERVICE = snlua logger gate harbor
LUA_CLIB = skynet \
  client \
  bson md5 sproto lpeg $(TLS_MODULE)

LUA_CLIB_SKYNET = \
  lua-skynet.c lua-seri.c \
  lua-socket.c \
  lua-mongo.c \
  lua-netpack.c \
  lua-memory.c \
  lua-multicast.c \
  lua-cluster.c \
  lua-crypt.c lsha1.c \
  lua-sharedata.c \
  lua-stm.c \
  lua-debugchannel.c \
  lua-datasheet.c \
  lua-sharetable.c \
  \

SKYNET_SRC = skynet_main.c skynet_handle.c skynet_module.c skynet_mq.c \
  skynet_server.c skynet_start.c skynet_timer.c skynet_error.c \
  skynet_harbor.c skynet_env.c skynet_monitor.c skynet_socket.c socket_server.c \
  malloc_hook.c skynet_daemon.c skynet_log.c

次に、all というエントリがあります。

まず最初の文を分析します。

all : \
  $(SKYNET_BUILD_PATH)/skynet \
  
LUA_LIB ?= $(LUA_STATICLIB) 

# 'cc -g -O2 -Wall -I3rd/lua  -o skynet skynet-src/skynet_main.c skynet-src/skynet_handle.c skynet-src/skynet_module.c skynet-src/skynet_mq.c skynet-src/skynet_server.c skynet-src/skynet_start.c skynet-src/skynet_timer.c skynet-src/skynet_error.c skynet-src/skynet_harbor.c skynet-src/skynet_env.c skynet-src/skynet_monitor.c skynet-src/skynet_socket.c skynet-src/socket_server.c skynet-src/malloc_hook.c skynet-src/skynet_daemon.c skynet-src/skynet_log.c 3rd/lua/liblua.a 3rd/jemalloc/lib/libjemalloc_pic.a -Iskynet-src -I3rd/jemalloc/include/jemalloc  -Wl,-E -lpthread -lm -ldl -lrt '
# 先决条件中skynet-src下的文件是已经存在的,$(LUA_LIB) 在下文中定义,$(MALLOC_STATICLIB)在前文中已经定义
$(SKYNET_BUILD_PATH)/skynet : $(foreach v, $(SKYNET_SRC), skynet-src/$(v)) $(LUA_LIB) $(MALLOC_STATICLIB)
	$(CC) $(CFLAGS) -o $@ $^ -Iskynet-src -I$(JEMALLOC_INC) $(LDFLAGS) $(EXPORT) $(SKYNET_LIBS) $(SKYNET_DEFINES)
	
# 执行3rd/lua下的Makefile
$(LUA_STATICLIB) :
	cd 3rd/lua && $(MAKE) CC='$(CC) -std=gnu99' $(PLAT)

  

次に、全体で 2 番目の文を見てください。

all:   $(foreach v, $(CSERVICE), $(CSERVICE_PATH)/$(v).so) \

$(LUA_CLIB_PATH) :
	mkdir $(LUA_CLIB_PATH)

$(CSERVICE_PATH) :
	mkdir $(CSERVICE_PATH)

# 定义了模板
define CSERVICE_TEMP
  $$(CSERVICE_PATH)/$(1).so : service-src/service_$(1).c | $$(CSERVICE_PATH)
	$$(CC) $$(CFLAGS) $$(SHARED) $$< -o $$@ -Iskynet-src
endef	

# https://www.gnu.org/software/make/manual/make.html#Eval-Function
# such as: cc -g -O2 -Wall -I3rd/lua  -fPIC --shared service-src/service_snlua.c -o cservice/snlua.so -Iskynet-src
$(foreach v, $(CSERVICE), $(eval $(call CSERVICE_TEMP,$(v))))

合計 3 番目の文は、lua の 3 つの部分からなるライブラリに対応します。

all : $(foreach v, $(LUA_CLIB), $(LUA_CLIB_PATH)/$(v).so) $(LUA_CLIB_PATH)/skynet.so : $(addprefix lualib-src/,$(LUA_CLIB_SKYNET)) | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@$(LUA_CLIB_PATH)/md5.so : 3rd/lua-md5/md5.c 3rd/lua-md5/md5lib.c 3rd/lua-md5/compat-5.2.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) -I3rd/lua-md5 $^ -o $@ $(LUA_CLIB_PATH)/client.so : lualib-src/lua-clientsocket.c lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -lpthread$(LUA_CLIB_PATH)/sproto.so : lualib-src/sproto/sproto.c lualib-src/sproto/lsproto.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) -Ilualib-src/sproto $^ -o $@ $(LUA_CLIB_PATH)/ltls.so : lualib-src/ltls.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) -Iskynet-src -L$(TLS_LIB) -I$(TLS_INC) $^ -o $@ -lssl$(LUA_CLIB_PATH)/lpeg.so : 3rd/lpeg/lpcap.c 3rd/lpeg/lpcode.c 3rd/lpeg/lpprint.c 3rd/lpeg/lptree.c 3rd/lpeg/lpvm.c | $(LUA_CLIB_PATH)	$(CC) $(CFLAGS) $(SHARED) -I3rd/lpeg $^ -o $@ 

付録

gcc 関連のパラメータ:

オプション 説明
-g デバッグ情報を生成します。GNU デバッガーはこの情報を使用できます。
-O または -O1 生成されたコードを最適化します。
-O2 高度な最適化。
-壁 すべての警告メッセージを生成します。
-I (大文字のi ) ヘッダファイルのパスを指定します(相対パスまたはフェルトパス、相対パスを推奨)
-Wl、オプション このオプションはオプションをリンカに渡します。オプションにカンマがある場合、オプションは複数のオプションに分割されてリンカに渡されます。
-E C プリコンパイラのみを実行します。
-lpスレッド スレッド ライブラリをリンクします。これは自分でコンパイルしたライブラリでも構いません
-lm コンパイル時に数学ライブラリをリンクします
-ldl 動的ライブラリを明示的にロードする動的関数ライブラリのリンク
-lrt リンクリアルタイムライブラリ(リアルタイム)
-l (小文字の L) リンクするライブラリの名前を指定します (リンク libc.a: -lc リンク ダイナミック ライブラリ: libc.so: -lc 注: -l の直後にライブラリ名 "lib" と ".so" または ".a" を追加します) )
-o ターゲット名を指定します。デフォルトでは、gcc によってコンパイルされたファイルは a.out です。

おすすめ

転載: blog.csdn.net/sayWhat_sayHello/article/details/119046183