redis源码导入clion
文章目录
背景
学习redis,看看源码,但是发现redis是直接使用make构建的,makefile晦涩难懂,本文在前人的基础之上使用cmake重构一下,导入到自己的ide里面。直接对面源进行debug.
环境
redis是可以跨平台的,但是目前工作没见过windows的redis,所以直接在linux系统下面操作,开发工具clion(idea的亲兄弟,java开发者最爱)
deepinv20+clion
redis3.0
redis3.0不直接采用github的源码,因为目前有人做好了笔记可以直接拿来学习
本项目是注释版的 Redis 3.0 源码, 原始代码来自: https://github.com/antirez/redis 。
这份注释是我在创作新版《Redis 设计与实现》期间, 为了了解 Redis 的内部实现而制作的, 所有在书中有介绍的内容, 在源码中都进行了相应的注释。
在注释的过程中, 除了少量空格和空行方面的调整外, 没有对原始代码进行任何其他改动, 最大程度地保证了代码的“原汁原味”。
希望这份注释源码能给大家学习和了解 Redis 带来一点帮助。
另外, 新版《Redis 设计与实现》正在各大网店发售中, 希望大家可以多多支持这本书。
Have fun!
黄健宏(huangz)
2014 年 6 月 28 日
redis-3.0源码目录结构
文件 | 作用 |
---|---|
adlist.c 、 adlist.h |
双端链表数据结构的实现。 |
ae.c 、 ae.h 、 ae_epoll.c 、 ae_evport.c 、 ae_kqueue.c 、 ae_select.c |
事件处理器,以及各个具体实现。 |
anet.c 、 anet.h |
Redis 的异步网络框架,内容主要为对 socket 库的包装。 |
aof.c |
AOF 功能的实现。 |
asciilogo.h |
保存了 Redis 的 ASCII LOGO 。 |
bio.c 、 bio.h |
Redis 的后台 I/O 程序,用于将 I/O 操作放到子线程里面执行, 减少 I/O 操作对主线程的阻塞。 |
bitops.c |
二进制位操作命令的实现文件。 |
blocked.c |
用于实现 BLPOP 命令和 WAIT 命令的阻塞效果。 |
cluster.c 、 cluster.h |
Redis 的集群实现。 |
config.c 、 config.h |
Redis 的配置管理实现,负责读取并分析配置文件, 然后根据这些配置修改 Redis 服务器的各个选项。 |
crc16.c 、 crc64.c 、 crc64.h |
计算 CRC 校验和。 |
db.c |
数据库实现。 |
debug.c |
调试实现。 |
dict.c 、 dict.h |
字典数据结构的实现。 |
endianconv.c 、 endianconv.h |
二进制的大端、小端转换函数。 |
fmacros.h |
一些移植性方面的宏。 |
help.h |
utils/generate-command-help.rb 程序自动生成的命令帮助信息。 |
hyperloglog.c |
HyperLogLog 数据结构的实现。 |
intset.c 、 intset.h |
整数集合数据结构的实现,用于优化 SET 类型。 |
lzf_c.c 、 lzf_d.c 、 lzf.h 、 lzfP.h |
Redis 对字符串和 RDB 文件进行压缩时使用的 LZF 压缩算法的实现。 |
Makefile 、 Makefile.dep |
构建文件。 |
memtest.c |
内存测试。 |
mkreleasehdr.sh |
用于生成释出信息的脚本。 |
multi.c |
Redis 的事务实现。 |
networking.c |
Redis 的客户端网络操作库, 用于实现命令请求接收、发送命令回复等工作, 文件中的函数大多为 write 、 read 、 close 等函数的包装, 以及各种协议的分析和构建函数。 |
notify.c |
Redis 的数据库通知实现。 |
object.c |
Redis 的对象系统实现。 |
pqsort.c 、 pqsort.h |
快速排序(QuickSort)算法的实现。 |
pubsub.c |
发布与订阅功能的实现。 |
rand.c 、 rand.h |
伪随机数生成器。 |
rdb.c 、 rdb.h |
RDB 持久化功能的实现。 |
redisassert.h |
Redis 自建的断言系统。 |
redis-benchmark.c |
Redis 的性能测试程序。 |
redis.c |
负责服务器的启动、维护和关闭等事项。 |
redis-check-aof.c 、 redis-check-dump.c |
RDB 文件和 AOF 文件的合法性检查程序。 |
redis-cli.c |
Redis 客户端的实现。 |
redis.h |
Redis 的主要头文件,记录了 Redis 中的大部分数据结构, 包括服务器状态和客户端状态。 |
redis-trib.rb |
Redis 集群的管理程序。 |
release.c 、 release.h |
记录和生成 Redis 的释出版本信息。 |
replication.c |
复制功能的实现。 |
rio.c 、 rio.h |
Redis 对文件 I/O 函数的包装, 在普通 I/O 函数的基础上增加了显式缓存、以及计算校验和等功能。 |
scripting.c |
脚本功能的实现。 |
sds.c 、 sds.h |
SDS 数据结构的实现,SDS 为 Redis 的默认字符串表示。 |
sentinel.c |
Redis Sentinel 的实现。 |
setproctitle.c |
进程环境设置函数。 |
sha1.c 、 sha1.h |
SHA1 校验和计算函数。 |
slowlog.c 、 slowlog.h |
慢查询功能的实现。 |
solarisfixes.h |
针对 Solaris 系统的补丁。 |
sort.c |
SORT 命令的实现。 |
syncio.c |
同步 I/O 操作。 |
testhelp.h |
测试辅助宏。 |
t_hash.c 、 t_list.c 、 t_set.c 、 t_string.c 、 t_zset.c |
定义了 Redis 的各种数据类型,以及这些数据类型的命令。 |
util.c 、 util.h |
各种辅助函数。 |
valgrind.sup |
valgrind 的suppression文件。 |
version.h |
记录了 Redis 的版本号。 |
ziplist.c 、 ziplist.h |
ZIPLIST 数据结构的实现,用于优化 LIST 类型。 |
zipmap.c 、 zipmap.h |
ZIPMAP 数据结构的实现,在 Redis 2.6 以前用与优化 HASH 类型, Redis 2.6 开始已经废弃。 |
zmalloc.c 、 zmalloc.h |
内存管理程序。 |
导入之后的目录结构
CMakeLists.txt的编写,在相应目录创建CMakeLists.txt
根目录
#指定cmake最低版本
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
#项目名称
project(redis-3.0 VERSION 3.0)
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type defined; defaulting to 'Debug'")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
"The type of build. Possible values are: Debug, Release, RelWithDebInfo and MinSizeRel.")
endif()
message(STATUS "Host is: ${CMAKE_HOST_SYSTEM}. Build target is: ${CMAKE_SYSTEM}")
get_filename_component(REDIS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
message(STATUS "Project root directory is: ${REDIS_ROOT}")
# Just for debugging when handling a new platform.
if (false)
message("C++ compiler supports these language features:")
foreach(i ${
CMAKE_CXX_COMPILE_FEATURES})
message(" ${i}")
endforeach()
endif()
message(STATUS "Generating release.h...")
#这个比较重要,会生成release.h到src目录下面
execute_process(
COMMAND sh -c ./mkreleasehdr.sh
WORKING_DIRECTORY ${
REDIS_ROOT}/src/
)
#子目录的配置
add_subdirectory(deps)
#redis服务的源码文件,网上抄
set(SRC_SERVER
src/adlist.c src/ae.c src/anet.c src/dict.c src/redis.c src/sds.c src/zmalloc.c
src/lzf_c.c src/lzf_d.c src/pqsort.c src/zipmap.c src/sha1.c src/ziplist.c src/release.c src/networking.c src/util.c src/object.c src/db.c src/replication.c src/rdb.c src/t_string.c src/t_list.c src/t_set.c src/t_zset.c src/t_hash.c src/config.c src/aof.c src/pubsub.c src/multi.c src/debug.c src/sort.c src/intset.c src/syncio.c src/cluster.c src/crc16.c src/endianconv.c src/slowlog.c src/scripting.c src/bio.c src/rio.c src/rand.c src/memtest.c src/crc64.c src/bitops.c src/sentinel.c src/notify.c src/setproctitle.c src/blocked.c src/hyperloglog.c
)
#redistribute-cli客户段的源码,网上抄
set(SRC_CLI
src/anet.c src/sds.c src/adlist.c src/redis-cli.c src/zmalloc.c src/release.c src/anet.c src/ae.c src/crc64.c
)
if (${
CMAKE_SYSTEM_NAME} MATCHES "Linux")
# better not to work with jemalloc
endif()
# 生成两个可执行文件
add_executable(redis-server ${
SRC_SERVER})
add_executable(redis-cli ${
SRC_CLI})
#一直设置,直接从网上抄
set_property(TARGET redis-server PROPERTY C_STANDARD 99)
set_property(TARGET redis-server PROPERTY CXX_STANDARD 11)
set_property(TARGET redis-server PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET redis-cli PROPERTY C_STANDARD 99)
set_property(TARGET redis-cli PROPERTY CXX_STANDARD 11)
set_property(TARGET redis-cli PROPERTY CXX_STANDARD_REQUIRED ON)
## link_directories(deps/hiredis/ deps/linenoise/ diredeps/lua/src)
# 链接动/静态库文件目录
target_include_directories(redis-server
PRIVATE ${
REDIS_ROOT}/deps/hiredis
PRIVATE ${
REDIS_ROOT}/deps/linenoise
# PRIVATE ${
REDIS_ROOT}/deps/jemalloc
PRIVATE ${
REDIS_ROOT}/deps/lua/src
)
# 链接动/静态
target_include_directories(redis-cli
PRIVATE ${
REDIS_ROOT}/deps/hiredis
PRIVATE ${
REDIS_ROOT}/deps/linenoise
# PRIVATE ${
REDIS_ROOT}/deps/jemalloc
PRIVATE ${
REDIS_ROOT}/deps/lua/src
)
target_link_libraries(redis-server
#多线程,系统库
PRIVATE pthread
#m不知道啥
PRIVATE m
# lua和其他两个都是源码里面有的
PRIVATE lua
PRIVATE linenoise
PRIVATE hiredis
)
target_link_libraries(redis-cli
PRIVATE pthread
PRIVATE m
PRIVATE linenoise
PRIVATE hiredis
)
deps
#添加自己目录配置
add_subdirectory (hiredis)
add_subdirectory(linenoise)
add_subdirectory(lua)
deps/hiredis
#生成一个静态库
add_library(hiredis STATIC
hiredis.c
net.c
dict.c
net.c
sds.c
async.c
)
deps/jemalloc
作用位置(像内存分配的,暂时可不管)
deps/linenoise
add_library(linenoise
linenoise.c
)
deps/lua
#这个指令是把整个目录的所有文件作为变量,免得一个一个的加
aux_source_directory (${
PROJECT_SOURCE_DIR}/deps/lua/src LUA_SRC)
add_library(lua STATIC ${
LUA_SRC})
reload项目
重点在于redis-server和redis-cli
redis6.0
fork源码
redis源码github
2.git clone 切换到6.0分支
3. 导入到clion
4.CMakeLists.txt的编写
根目录
#制定cmake最小版本
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
#项目名称
project(redis VERSION 6.0)
set(CMAKE_BUILD_TYPE "Debug")
get_filename_component(REDIS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type defined; defaulting to 'Debug'")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
"The type of build. Possible values are: Debug, Release, RelWithDebInfo and MinSizeRel.")
endif()
message(STATUS "Host is: ${CMAKE_HOST_SYSTEM}. Build target is: ${CMAKE_SYSTEM}")
get_filename_component(REDIS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
message(STATUS "Project root directory is: ${REDIS_ROOT}")
# Just for debugging when handling a new platform.
if (false)
message("C++ compiler supports these language features:")
foreach(i ${
CMAKE_CXX_COMPILE_FEATURES})
message(" ${i}")
endforeach()
endif()
#zai src目录生成release.h 比较重要
message(STATUS "Generating release.h...")
execute_process(
COMMAND sh -c ./mkreleasehdr.sh
WORKING_DIRECTORY ${
REDIS_ROOT}/src/
)
#子目录构建配置
add_subdirectory(deps)
#这个感觉不是重点先封着
#add_subdirectory(src/modules)
# redis源码文件,网上抄
set(SRC_SERVER_TMP
src/acl.c
src/adlist.c
src/ae.c
# src/ae_kqueue.c
src/anet.c
src/aof.c
src/bio.c
src/bitops.c
src/blocked.c
src/childinfo.c
src/cluster.c
src/config.c
src/connection.c
src/crc16.c
src/crc64.c
src/db.c
src/debug.c
src/defrag.c
src/dict.c
src/endianconv.c
src/evict.c
src/expire.c
src/geo.c
src/geohash.c
src/geohash_helper.c
src/gopher.c
src/hyperloglog.c
src/intset.c
src/latency.c
src/lazyfree.c
src/listpack.c
src/localtime.c
src/lolwut.c
src/lolwut5.c
src/lolwut6.c
src/lzf_c.c
src/lzf_d.c
src/memtest.c
src/module.c
src/multi.c
src/networking.c
src/notify.c
src/object.c
src/pqsort.c
src/pubsub.c
src/quicklist.c
src/rand.c
src/rax.c
src/rdb.c
src/redis-check-aof.c
src/redis-check-rdb.c
src/release.c
src/replication.c
src/rio.c
src/scripting.c
src/sds.c
src/sentinel.c
src/setproctitle.c
src/sha1.c
src/sha256.c
src/siphash.c
src/slowlog.c
src/sort.c
src/sparkline.c
src/syncio.c
src/t_hash.c
src/t_list.c
src/t_set.c
src/t_stream.c
src/t_string.c
src/t_zset.c
src/tls.c
src/tracking.c
src/util.c
src/ziplist.c
src/zipmap.c
src/zmalloc.c
src/timeout.c
src/crcspeed.c
)
set(SRC_SERVER src/server.c ${
SRC_SERVER_TMP})
# redis客户端源码文件,网上抄
set(SRC_CLI
src/anet.c
src/sds.c
src/adlist.c
src/redis-cli.c
src/zmalloc.c
src/release.c
src/anet.c
src/ae.c
src/crc64.c
src/crcspeed.c
src/dict.c
src/crc16.c
src/siphash.c
)
#这个指令不需要,不用自己制定可执行文件的输出位置,clion自己有 cmake-build-debug
#set(EXECUTABLE_OUTPUT_PATH src)
#库所在目录
link_directories(deps/linenoise/ deps/lua/src deps/hiredis)
# redis-server
add_executable(redis-server ${
SRC_SERVER})
target_include_directories(redis-server
PRIVATE ${
REDIS_ROOT}/deps/linenoise
PRIVATE ${
REDIS_ROOT}/deps/hiredis
PRIVATE ${
REDIS_ROOT}/deps/lua/src)
target_link_libraries(redis-server
PRIVATE pthread
PRIVATE m
PRIVATE lua
PRIVATE linenoise
PRIVATE hiredis
#这一步,是因为出现dlopen找不到等报错,dlopen,dlclose等是系统调用动态库的函数
${
CMAKE_DL_LIBS}
)
# redis-cli
add_executable(redis-cli ${
SRC_CLI})
target_include_directories(redis-cli
PRIVATE ${
REDIS_ROOT}/deps/linenoise
PRIVATE ${
REDIS_ROOT}/deps/hiredis
PRIVATE ${
REDIS_ROOT}/deps/lua/src)
target_link_libraries(redis-cli
PRIVATE pthread
PRIVATE m
PRIVATE linenoise
PRIVATE hiredis
)
deps/hiredis
这里已经有了
add_library(hiredis STATIC
#这个在master是有的,6.0分支没有了
#alloc.c
async.c
dict.c
hiredis.c
net.c
read.c
sds.c
sockcompat.c)
# 注释的源码自带的
#[[CMAKE_MINIMUM_REQUIRED(VERSION 3.4.0)
INCLUDE(GNUInstallDirs)
PROJECT(hiredis)
OPTION(ENABLE_SSL "Build hiredis_ssl for SSL support" OFF)
MACRO(getVersionBit name)
SET(VERSION_REGEX "^#define ${name} (.+)$")
FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h"
VERSION_BIT REGEX ${
VERSION_REGEX})
STRING(REGEX REPLACE ${
VERSION_REGEX} "\\1" ${
name} "${VERSION_BIT}")
ENDMACRO(getVersionBit)
getVersionBit(HIREDIS_MAJOR)
getVersionBit(HIREDIS_MINOR)
getVersionBit(HIREDIS_PATCH)
getVersionBit(HIREDIS_SONAME)
SET(VERSION "${HIREDIS_MAJOR}.${HIREDIS_MINOR}.${HIREDIS_PATCH}")
MESSAGE("Detected version: ${VERSION}")
PROJECT(hiredis VERSION "${VERSION}")
SET(ENABLE_EXAMPLES OFF CACHE BOOL "Enable building hiredis examples")
ADD_LIBRARY(hiredis SHARED
async.c
dict.c
hiredis.c
net.c
read.c
sds.c
sockcompat.c)
SET_TARGET_PROPERTIES(hiredis
PROPERTIES
VERSION "${HIREDIS_SONAME}")
IF(WIN32 OR MINGW)
TARGET_LINK_LIBRARIES(hiredis PRIVATE ws2_32)
ENDIF()
TARGET_INCLUDE_DIRECTORIES(hiredis PUBLIC .)
CONFIGURE_FILE(hiredis.pc.in hiredis.pc @ONLY)
INSTALL(TARGETS hiredis
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
INSTALL(FILES hiredis.h read.h sds.h async.h
DESTINATION ${
CMAKE_INSTALL_INCLUDEDIR}/hiredis)
INSTALL(DIRECTORY adapters
DESTINATION ${
CMAKE_INSTALL_INCLUDEDIR}/hiredis)
INSTALL(FILES ${
CMAKE_CURRENT_BINARY_DIR}/hiredis.pc
DESTINATION ${
CMAKE_INSTALL_LIBDIR}/pkgconfig)
IF(ENABLE_SSL)
IF (NOT OPENSSL_ROOT_DIR)
IF (APPLE)
SET(OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
ENDIF()
ENDIF()
FIND_PACKAGE(OpenSSL REQUIRED)
ADD_LIBRARY(hiredis_ssl SHARED
ssl.c)
TARGET_INCLUDE_DIRECTORIES(hiredis_ssl PRIVATE "${OPENSSL_INCLUDE_DIR}")
TARGET_LINK_LIBRARIES(hiredis_ssl PRIVATE ${
OPENSSL_LIBRARIES})
CONFIGURE_FILE(hiredis_ssl.pc.in hiredis_ssl.pc @ONLY)
INSTALL(TARGETS hiredis_ssl
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
INSTALL(FILES hiredis_ssl.h
DESTINATION ${
CMAKE_INSTALL_INCLUDEDIR}/hiredis)
INSTALL(FILES ${
CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl.pc
DESTINATION ${
CMAKE_INSTALL_LIBDIR}/pkgconfig)
ENDIF()
IF(NOT (WIN32 OR MINGW))
ENABLE_TESTING()
ADD_EXECUTABLE(hiredis-test test.c)
TARGET_LINK_LIBRARIES(hiredis-test hiredis)
ADD_TEST(NAME hiredis-test
COMMAND ${
CMAKE_CURRENT_SOURCE_DIR}/test.sh)
ENDIF()
# Add examples
IF(ENABLE_EXAMPLES)
ADD_SUBDIRECTORY(examples)
ENDIF(ENABLE_EXAMPLES)]]
其他目录的配置同3.0
唯一改动的代码是server里面的,里面报错函数找不到,暂时注释(这里有条件编译,可有可无的那种)
启动
使用
县启动server然后启动cli
注意点
- 3.0版本按照网上的基本没问题
- 6.0的版本需要微调一下,windows和linus还略有不同,重点在于CMakeLists.txt的编写,可以参考网上的其他文章
参考文章:https://blog.csdn.net/Nuan_Feng/article/details/108542440?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-13.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-13.no_search_link
参考视频:https://www.bilibili.com/video/BV1vE411v7cR/?spm_id_from=autoNext