把redis源码的linux网络库提取出来,自己封装成通用库使用(1)(★firecat推荐★)

简介: 把redis源码的linux网络库提取出来,自己封装成通用库使用(★firecat推荐★)

如题,redis网络库是基于单进程单线程的机制实现,简单高效。可用直接将它提取出来使用。Redis网络库是一个单线程EPOLL模型的网络库,和Memcached使用的libevent相比,它没有那么庞大,代码一共2000多行,因此比较容易分析。本篇拿出了Redis网络部分的代码,添加了应用层buffer,让它现在变成了一个可以实现tcp通信的程序。


Redis网络库是一个单线程EPOLL模型,也就是说接收连接和处理读写请求包括定时器任务都被这一个线程包揽,真的是又当爹又当妈,但是效率一定比多线程差吗?不见得。

单线程的好处有:

1:避免线程切换带来的上下文切换开销。

2:单线程避免了锁的争用。

3:对于一个内存型数据库,如果不考虑数据持久化,也就是读写物理磁盘,不会有阻塞操作,内存操作是非常快的。


#The network library from redis v4.0.9 -- https://github.com/antirez/redis

#把源码以下文件提取出来即可使用,无需作任何修改。

#/redis-unstable/src/ae.c

#/redis-unstable/src/ae.h

#/redis-unstable/src/ae_epoll.c

#/redis-unstable/src/ae_evport.c

#/redis-unstable/src/ae_kqueue.c

#/redis-unstable/src/ae_select.c

#/redis-unstable/src/anet.c

#/redis-unstable/src/anet.h

#/redis-unstable/src/atomicvar.h

#/redis-unstable/src/config.h

#/redis-unstable/src/fmacros.h

#/redis-unstable/src/zmalloc.c

#/redis-unstable/src/zmalloc.h


根据内存分配器的使用不同,区别为:


完整的工程源码下载(malloc使用原生的libc):https://download.csdn.net/download/libaineu2004/10468733


完整的工程源码下载(malloc使用jemalloc):https://download.csdn.net/download/libaineu2004/10468734


如果不清楚libc和jemalloc的概念,请看http://blog.csdn.net/libaineu2004/article/details/79400357


jemalloc的源码下载和编译:https://blog.csdn.net/libaineu2004/article/details/79402103




CMakeLists.txt(使用libc)


cmake_minimum_required(VERSION 2.8)
#The network library from redis v4.0.9 -- https://github.com/antirez/redis
#No changes were made.
#/redis-unstable/src/ae.c
#/redis-unstable/src/ae.h
#/redis-unstable/src/ae_epoll.c
#/redis-unstable/src/ae_evport.c
#/redis-unstable/src/ae_kqueue.c
#/redis-unstable/src/ae_select.c
#/redis-unstable/src/anet.c
#/redis-unstable/src/anet.h
#/redis-unstable/src/atomicvar.h
#/redis-unstable/src/config.h
#/redis-unstable/src/fmacros.h
#/redis-unstable/src/zmalloc.c
#/redis-unstable/src/zmalloc.h
project(myRedisNetDemo)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -g")
set(REDIS_SRC ./redis_network/ae.c ./redis_network/anet.c ./redis_network/zmalloc.c)
include_directories(./redis_network) #https://github.com/antirez/redis
add_executable(${PROJECT_NAME} example_firecat.c buffer.c ${REDIS_SRC})
CMakeLists.txt(使用jemalloc)
cmake_minimum_required(VERSION 2.8)
#The network library from redis v4.0.9 -- https://github.com/antirez/redis
#No changes were made.
#/redis-unstable/src/ae.c
#/redis-unstable/src/ae.h
#/redis-unstable/src/ae_epoll.c
#/redis-unstable/src/ae_evport.c
#/redis-unstable/src/ae_kqueue.c
#/redis-unstable/src/ae_select.c
#/redis-unstable/src/anet.c
#/redis-unstable/src/anet.h
#/redis-unstable/src/atomicvar.h
#/redis-unstable/src/config.h
#/redis-unstable/src/fmacros.h
#/redis-unstable/src/zmalloc.c
#/redis-unstable/src/zmalloc.h
project(myRedisNetDemo)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -g")
set(REDIS_SRC ./redis_network/ae.c ./redis_network/anet.c ./redis_network/zmalloc.c)
find_library(JEMALLOC_LIB libjemalloc.so /usr/local/lib)
IF (NOT JEMALLOC_LIB)
    MESSAGE(FATAL_ERROR "libjemalloc not found")
ENDIF(NOT JEMALLOC_LIB)
SET(JEMALLOC_INCLUDE_DIR /usr/include/jemalloc)
SET(JEMALLOC_LIB /usr/local/lib)
INCLUDE_DIRECTORIES(./redis_network) #https://github.com/antirez/redis
INCLUDE_DIRECTORIES(${JEMALLOC_INCLUDE_DIR})
LINK_DIRECTORIES(${JEMALLOC_LIB})
#ADD_EXECUTABLE必须在TARGET_LINK_LIBRARIES前面,否则会报错
ADD_EXECUTABLE(${PROJECT_NAME} example_firecat.c buffer.c ${REDIS_SRC})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} jemalloc)




buffer.h,关注头文件包含:


#include "zmalloc.h"//libc要用这个
//#include "redis_network/zmalloc.h"//或者libc要用这个
//#include "myjemalloc.h"//jemalloc要用这个
#ifndef MYREDISNET_AEBUFFER_H
#define MYREDISNET_AEBUFFER_H
/// 《Linux多线程服务端编程:使用muduo C++网络库》陈硕著 7.4章节,P204
/// https://github.com/chenshuo/muduo
/// muduo buf:A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
///
/// @code
/// +-------------------+------------------+------------------+
/// | prependable bytes |  readable bytes  |  writable bytes  |
/// |                   |     (CONTENT)    |                  |
/// +-------------------+------------------+------------------+
/// |                   |                  |                  |
/// 0      <=      readerIndex   <=   writerIndex    <=     size
///
/// @endcode
//#include "zmalloc.h"//不能直接包含这个头文件,编译会报错 basic_string.h:2423:7: error: ‘__str’ was not declared in this scope
#include "myjemalloc.h"//要用这个
#include <sys/types.h>
#define DEFAULT_BUFF_SIZE        1024
typedef struct {
    unsigned char *buff;
    size_t size;
    size_t read_idx;
    size_t write_idx;
} buffer_t;
buffer_t *alloc_buffer();
void free_buffer(buffer_t *buffer);
void check_buffer_size(buffer_t *buffer, size_t avlid_size);
size_t get_readable_size(buffer_t *buffer);
size_t get_writeable_size(buffer_t *buffer);
#endif //MYREDISNET_AEBUFFER_H




myjemalloc.h -- 本人自定义的头文件


#ifndef __MYJEMALLOC_H
#define __MYJEMALLOC_H
#include <jemalloc/jemalloc.h>
#define zmalloc(size) je_malloc(size)
#define zcalloc(count,size) je_calloc(count,size)
#define zrealloc(ptr,size) je_realloc(ptr,size)
#define zfree(ptr) je_free(ptr)
#define zmallocx(s
ize,flags) je_mallocx(size,flags)
#define zdallocx(ptr,flags) je_dallocx(ptr,flags)
#endif



buffer.c

#include "buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
buffer_t *alloc_buffer()
{
    buffer_t *buffer = zmalloc(sizeof(buffer_t));
    if (buffer == NULL) {
        goto err;
    }
    buffer->buff = zmalloc(DEFAULT_BUFF_SIZE);
    buffer->size = DEFAULT_BUFF_SIZE;
    buffer->read_idx = 0;
    buffer->write_idx = 0;
    return buffer;
err:
    if (buffer) {
        zfree(buffer->buff);
        buffer->buff = NULL;
        zfree(buffer);
        buffer = NULL;
    }
    return NULL;
}
void free_buffer(buffer_t *buffer)
{
    if (buffer) {
        zfree(buffer->buff);
        buffer->buff = NULL;
        zfree(buffer);
        buffer = NULL;
    }
}
void check_buffer_size(buffer_t *buffer, size_t avlid_size)
{
    if (buffer->read_idx > DEFAULT_BUFF_SIZE) {
        size_t data_len = get_readable_size(buffer);
        memmove(buffer->buff, buffer->buff + buffer->read_idx, data_len);
        buffer->read_idx = 0;
        buffer->write_idx = data_len;
    }
    if (get_writeable_size(buffer) < avlid_size) {
        size_t new_size = buffer->size + avlid_size;
        buffer->buff = zrealloc(buffer->buff, new_size);
        buffer->size = new_size;
    }
}
size_t get_readable_size(buffer_t *buffer)
{
    assert(buffer->size >= buffer->write_idx);
    assert(buffer->read_idx <= buffer->write_idx);
    return buffer->write_idx - buffer->read_idx;
}
size_t get_writeable_size(buffer_t *buffer)
{
    assert(buffer->size >= buffer->write_idx);
    assert(buffer->read_idx <= buffer->write_idx);
    return buffer->size - buffer->write_idx;
}


相关文章
|
5月前
|
C++
基于Reactor模型的高性能网络库之地址篇
这段代码定义了一个 InetAddress 类,是 C++ 网络编程中用于封装 IPv4 地址和端口的常见做法。该类的主要作用是方便地表示和操作一个网络地址(IP + 端口)
321 58
|
5月前
|
网络协议 算法 Java
基于Reactor模型的高性能网络库之Tcpserver组件-上层调度器
TcpServer 是一个用于管理 TCP 连接的类,包含成员变量如事件循环(EventLoop)、连接池(ConnectionMap)和回调函数等。其主要功能包括监听新连接、设置线程池、启动服务器及处理连接事件。通过 Acceptor 接收新连接,并使用轮询算法将连接分配给子事件循环(subloop)进行读写操作。调用链从 start() 开始,经由线程池启动和 Acceptor 监听,最终由 TcpConnection 管理具体连接的事件处理。
231 2
|
5月前
基于Reactor模型的高性能网络库之Tcpconnection组件
TcpConnection 由 subLoop 管理 connfd,负责处理具体连接。它封装了连接套接字,通过 Channel 监听可读、可写、关闭、错误等
179 1
|
5月前
|
负载均衡 算法 安全
基于Reactor模式的高性能网络库之线程池组件设计篇
EventLoopThreadPool 是 Reactor 模式中实现“一个主线程 + 多个工作线程”的关键组件,用于高效管理多个 EventLoop 并在多核 CPU 上分担高并发 I/O 压力。通过封装 Thread 类和 EventLoopThread,实现线程创建、管理和事件循环的调度,形成线程池结构。每个 EventLoopThread 管理一个子线程与对应的 EventLoop(subloop),主线程(base loop)通过负载均衡算法将任务派发至各 subloop,从而提升系统性能与并发处理能力。
328 3
|
5月前
基于Reactor模式的高性能网络库github地址
https://github.com/zyi30/reactor-net.git
154 0
|
5月前
基于Reactor模型的高性能网络库之Poller(EpollPoller)组件
封装底层 I/O 多路复用机制(如 epoll)的抽象类 Poller,提供统一接口支持多种实现。Poller 是一个抽象基类,定义了 Channel 管理、事件收集等核心功能,并与 EventLoop 绑定。其子类 EPollPoller 实现了基于 epoll 的具体操作,包括事件等待、Channel 更新和删除等。通过工厂方法可创建默认的 Poller 实例,实现多态调用。
332 60
|
5月前
|
安全 调度
基于Reactor模型的高性能网络库之核心调度器:EventLoop组件
它负责:监听事件(如 I/O 可读写、定时器)、分发事件、执行回调、管理事件源 Channel 等。
339 57
|
5月前
基于Reactor模型的高性能网络库之时间篇
是一个用于表示时间戳(精确到微秒)**的简单封装类
226 57
|
5月前
|
缓存 索引
基于Reactor模式的高性能网络库之缓冲区Buffer组件
Buffer 类用于处理 Socket I/O 缓存,负责数据读取、写入及内存管理。通过预分配空间和索引优化,减少内存拷贝与系统调用,提高网络通信效率,适用于 Reactor 模型中的异步非阻塞 IO 处理。
215 3
|
4月前
|
机器学习/深度学习 算法 数据库
基于GoogleNet深度学习网络和GEI步态能量提取的步态识别算法matlab仿真,数据库采用CASIA库
本项目基于GoogleNet深度学习网络与GEI步态能量图提取技术,实现高精度步态识别。采用CASI库训练模型,结合Inception模块多尺度特征提取与GEI图像能量整合,提升识别稳定性与准确率,适用于智能安防、身份验证等领域。