Directorio de artículos
Análisis del código fuente de Skynet
prefacio
La versión de este artículo es skynet v1.4.0. Lo inevitable para compilar skynet es hacer.
Este artículo analizará específicamente la implementación de make.
Acerca de la marca, puede consultar el blog de Ruan Yifeng .
Además, este artículo solo involucra el Makefile de nivel superior y no analiza el Makefile en el subdirectorio.
El apéndice es algunos parámetros de GCC.
texto
Cuando ejecutamos en el directorio skynet, make linux
en realidad estamos ejecutando Makefile
los comandos en él. En la primera línea del archivo hay esta declaración:
include platform.mk
plataforma.mk
La lógica es más o menos la siguiente:
-
Determine si se pasa la plataforma correcta en
linux freebsd macosx
. Si no, salga con un mensaje de error: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'
Si se pasa la plataforma incorrecta, habrá una impresión similar:
wyw@DESKTOP-GJ20UDC:~/skynet$ make l make: *** No rule to make target 'l'. Stop.
-
Se establecen diferentes variables según las diferentes plataformas, y las variables establecidas aquí se utilizarán en el Makefile. ej
make linux
. La ejecución hasta el último comando es la siguiente:# 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
Volviendo a Makefile, algunos valores relacionados con la plataforma se establecen después de incluir. Y se ejecuta make all
.
La lógica es más o menos la siguiente:
- generar jemalloc
- Generar partes relacionadas con skynet
jemalloc
Jemalloc es un asignador de memoria. Comparado con otros asignadores de memoria, su mayor ventaja radica en su alto rendimiento en situaciones de subprocesos múltiples y la reducción de la fragmentación de la memoria.
Lea el README.md en el proyecto skynet. Hay una oración como esta:
Para Linux, instale autoconf primero para jemalloc
La razón se revelará más adelante, primero analicemos el Makefile.
Declaración de inicio:
# 定义变量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
skynet
Hay más contenido en esta parte, primero la definición de algunas variables.
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
Luego está la entrada all:
Primero analice la primera oración en total:
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)
A continuación, mira la segunda oración en total:
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))))
La tercera frase en total corresponde a la biblioteca tripartita de lua:
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 $@
apéndice
parámetros relacionados con gcc:
opciones | explicar |
---|---|
-gramo | Generar información de depuración. El depurador GNU puede usar esta información. |
-O o -O1 | Optimizar el código generado. |
-O2 | optimización avanzada. |
-Muro | Genera todos los mensajes de advertencia. |
-I ( i mayúscula ) | Especifique la ruta del archivo de encabezado (ruta relativa o ruta fiel, se recomienda la ruta relativa) |
-Wl, opción | Esta opción pasa la opción al enlazador; si hay una coma en la opción, la opción se divide en varias opciones y luego se pasa al enlazador. |
-MI | Solo ejecute el precompilador C. |
-lpthread | Vincule la biblioteca de subprocesos, que puede ser una biblioteca compilada por usted mismo |
-lm | Al compilar, vincular la biblioteca de matemáticas |
-ldl | Vincular una biblioteca de funciones dinámicas que carga explícitamente una biblioteca dinámica |
-lrt | Enlace biblioteca en tiempo real (tiempo real) |
-l (L minúscula) | Especifique el nombre de la biblioteca a vincular (enlace libc.a: -lc enlace biblioteca dinámica: libc.so: -lc Nota: agregue el nombre de la biblioteca "lib" y ".so" o ".a" directamente después de -l ) |
-o | Especifique el nombre de destino. De forma predeterminada, el archivo compilado por gcc es a.out |