C语言企业项目实战(二)

简介: 教程来源 https://xcfsr.cn/category/software-dev.html C-Cache是企业级C语言缓存系统,采用模块化设计:清晰的目录结构(含server/protocol/datastore等)、CMake构建系统(支持多平台与Sanitizer)、高性能SDS动态字符串、渐进式哈希表(避免rehash卡顿)及内存分配器封装,兼顾性能、可维护性与生产就绪能力。

第二部分:项目结构与构建系统

2.1 目录结构规划
企业级项目必须有清晰、规范的目录结构,便于团队协作和长期维护。

c-cache/
├── CMakeLists.txt                    # 顶层CMake配置
├── README.md                         # 项目说明
├── LICENSE                           # 许可证
├── .gitignore                        # Git忽略文件
├── .clang-format                     # 代码格式化配置
├── .clang-tidy                       # 静态分析配置
│
├── src/                              # 源代码目录
│   ├── main.c                        # 程序入口
│   ├── server/                       # 服务器核心
│   │   ├── event_loop.h
│   │   ├── event_loop.c              # 事件循环(epoll封装)
│   │   ├── connection.h
│   │   ├── connection.c              # TCP连接管理
│   │   ├── acceptor.h
│   │   └── acceptor.c                # 监听器
│   │
│   ├── protocol/                     # 协议处理
│   │   ├── resp.h
│   │   ├── resp.c                    # RESP协议解析
│   │   ├── command.h
│   │   └── command.c                 # 命令分发与执行
│   │
│   ├── datastore/                    # 数据存储
│   │   ├── dict.h
│   │   ├── dict.c                    # 哈希表实现
│   │   ├── sds.h
│   │   ├── sds.c                     # 动态字符串
│   │   ├── object.h
│   │   ├── object.c                  # 数据对象(string/hash/list)
│   │   ├── expire.h
│   │   └── expire.c                  # 过期键管理
│   │
│   ├── persistence/                  # 持久化
│   │   ├── rdb.h
│   │   ├── rdb.c                     # RDB快照
│   │   ├── aof.h
│   │   └── aof.c                     # AOF日志
│   │
│   ├── replication/                  # 主从复制
│   │   ├── replication.h
│   │   └── replication.c             # 复制逻辑
│   │
│   ├── utils/                        # 工具函数
│   │   ├── alloc.h
│   │   ├── alloc.c                   # 内存分配器封装
│   │   ├── log.h
│   │   ├── log.c                     # 日志系统
│   │   ├── config.h
│   │   ├── config.c                  # 配置解析
│   │   ├── time.h
│   │   └── time.c                    # 时间工具
│   │
│   └── include/                      # 公共头文件
│       ├── version.h                 # 版本定义
│       └── error.h                   # 错误码定义
│
├── tests/                            # 测试目录
│   ├── unit/                         # 单元测试
│   │   ├── test_dict.c
│   │   ├── test_sds.c
│   │   └── test_resp.c
│   ├── integration/                  # 集成测试
│   │   └── test_server.c
│   └── benchmark/                    # 性能测试
│       └── bench_cache.c
│
├── deps/                             # 第三方依赖
│   ├── libevent/                     # libevent源码(可选)
│   └── jemalloc/                     # jemalloc源码(可选)
│
├── config/                           # 配置文件
│   ├── ccache.conf                   # 默认配置
│   └── ccache.example.conf           # 配置示例
│
├── scripts/                          # 脚本工具
│   ├── build.sh                      # 构建脚本
│   ├── run.sh                        # 运行脚本
│   ├── benchmark.sh                  # 性能测试脚本
│   └── cluster_setup.sh              # 集群部署脚本
│
└── docs/                             # 文档
    ├── architecture.md               # 架构设计
    ├── api.md                        # API文档
    └── deployment.md                 # 部署指南

2.2 CMake构建配置
企业级项目需要可靠的构建系统。CMake是C/C++项目的事实标准。

# CMakeLists.txt - 顶层配置
cmake_minimum_required(VERSION 3.15)
project(CCache VERSION 1.0.0 LANGUAGES C)

# ========== 全局配置 ==========
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# 设置编译选项
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    add_compile_options(-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter)
    add_compile_options(-fsanitize=address -fsanitize=undefined)
    add_link_options(-fsanitize=address -fsanitize=undefined)
else()
    add_compile_options(-O3 -DNDEBUG -flto -march=native)
    add_link_options(-flto)
endif()

# 平台检测
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    add_compile_options(-D__LINUX__)
    set(PLATFORM_LIBS pthread rt)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
    add_compile_options(-D__MACOS__)
    set(PLATFORM_LIBS pthread)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
    add_compile_options(-D__WINDOWS__)
    set(PLATFORM_LIBS ws2_32)
endif()

# ========== 第三方依赖 ==========
# 查找libevent(可选,也可自己实现epoll封装)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBEVENT REQUIRED libevent)

# 查找jemalloc(可选)
find_package(jemalloc)
if(jemalloc_FOUND)
    add_compile_options(-DUSE_JEMALLOC)
    set(EXTRA_LIBS ${EXTRA_LIBS} jemalloc::jemalloc)
endif()

# ========== 源代码组织 ==========
# 核心模块
set(CORE_SOURCES
    src/main.c
    src/server/event_loop.c
    src/server/connection.c
    src/server/acceptor.c
    src/protocol/resp.c
    src/protocol/command.c
    src/datastore/dict.c
    src/datastore/sds.c
    src/datastore/object.c
    src/datastore/expire.c
    src/persistence/rdb.c
    src/persistence/aof.c
    src/replication/replication.c
    src/utils/alloc.c
    src/utils/log.c
    src/utils/config.c
    src/utils/time.c
)

# 公共头文件目录
include_directories(
    src/include
    src
    ${LIBEVENT_INCLUDE_DIRS}
)

# 生成可执行文件
add_executable(ccache ${CORE_SOURCES})

# 链接库
target_link_libraries(ccache
    ${LIBEVENT_LIBRARIES}
    ${PLATFORM_LIBS}
    ${EXTRA_LIBS}
)

# ========== 安装配置 ==========
install(TARGETS ccache DESTINATION bin)
install(FILES config/ccache.conf DESTINATION etc)
install(DIRECTORY scripts/ DESTINATION bin/scripts)

# ========== 测试 ==========
enable_testing()
add_subdirectory(tests)

# ========== 打包配置 ==========
set(CPACK_GENERATOR "TGZ;ZIP")
set(CPACK_PACKAGE_NAME "ccache")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
include(CPack)

第三部分:核心数据结构实现

3.1 SDS(Simple Dynamic String)实现
C语言字符串的痛点:获取长度需要O(n)遍历、缓冲区溢出风险、二进制不安全。SDS是Redis采用的高性能字符串实现,我们将其作为C-Cache的基础组件。

// src/datastore/sds.h
#ifndef CCACHE_SDS_H
#define CCACHE_SDS_H

#include <stddef.h>
#include <stdint.h>

/* SD S头部结构(5种类型,根据字符串长度选择) */
#define SDS_TYPE_5  0  // 长度 < 32
#define SDS_TYPE_8  1  // 长度 < 256
#define SDS_TYPE_16 2  // 长度 < 64K
#define SDS_TYPE_32 3  // 长度 < 4GB
#define SDS_TYPE_64 4  // 长度 < 2^63

/* 内部使用的SDS头(内存布局:len + alloc + flags + buf[]) */
struct __attribute__((__packed__)) sdshdr8 {
    uint8_t len;      // 已使用长度
    uint8_t alloc;    // 分配的总长度(不含header和'\0')
    unsigned char flags; // 类型标识(低3位)
    char buf[];
};

struct __attribute__((__packed__)) sdshdr16 {
    uint16_t len;
    uint16_t alloc;
    unsigned char flags;
    char buf[];
};

struct __attribute__((__packed__)) sdshdr32 {
    uint32_t len;
    uint32_t alloc;
    unsigned char flags;
    char buf[];
};

struct __attribute__((__packed__)) sdshdr64 {
    uint64_t len;
    uint64_t alloc;
    unsigned char flags;
    char buf[];
};

/* SDS类型定义 */
typedef char* sds;

/* 基础操作API */
sds sdsnew(const char *init);
sds sdsnewlen(const void *init, size_t initlen);
sds sdsdup(const sds s);
void sdsfree(sds s);
size_t sdslen(const sds s);
size_t sdsavail(const sds s);
sds sdscatlen(sds s, const void *t, size_t len);
sds sdscat(sds s, const char *t);
sds sdscpylen(sds s, const char *t, size_t len);
sds sdscpy(sds s, const char *t);
sds sdsgrowzero(sds s, size_t len);
sds sdscatprintf(sds s, const char *fmt, ...);
void sdstrim(sds s, const char *cset);
void sdsrange(sds s, int start, int end);
int sdscmp(const sds s1, const sds s2);
sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
void sdsfreesplitres(sds *tokens, int count);
void sdstolower(sds s);
void sdstoupper(sds s);
sds sdsfromlonglong(long long value);

#endif // CCACHE_SDS_H
j// src/datastore/sds.c
#include "sds.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

/* 获取SDS头指针 */
static inline struct sdshdr8 *sdsheader8(const sds s) {
    return (struct sdshdr8 *)(s - sizeof(struct sdshdr8));
}

static inline struct sdshdr16 *sdsheader16(const sds s) {
    return (struct sdshdr16 *)(s - sizeof(struct sdshdr16));
}

static inline struct sdshdr32 *sdsheader32(const sds s) {
    return (struct sdshdr32 *)(s - sizeof(struct sdshdr32));
}

static inline struct sdshdr64 *sdsheader64(const sds s) {
    return (struct sdshdr64 *)(s - sizeof(struct sdshdr64));
}

/* 获取SDS类型 */
static inline char sdsflags(const sds s) {
    return s[-1];  // flags在buf前面一个字节
}

/* 获取SDS长度 - O(1)时间复杂度!*/
size_t sdslen(const sds s) {
    if (!s) return 0;
    unsigned char flags = sdsflags(s);
    switch(flags & SDS_TYPE_MASK) {
        case SDS_TYPE_5: return (size_t)((struct sdshdr5 *)s->buf)[-1] >> 3;
        case SDS_TYPE_8: return sdsheader8(s)->len;
        case SDS_TYPE_16: return sdsheader16(s)->len;
        case SDS_TYPE_32: return sdsheader32(s)->len;
        case SDS_TYPE_64: return sdsheader64(s)->len;
        default: return 0;
    }
}

/* 获取可用空间 */
size_t sdsavail(const sds s) {
    if (!s) return 0;
    unsigned char flags = sdsflags(s);
    switch(flags & SDS_TYPE_MASK) {
        case SDS_TYPE_5: return 0;
        case SDS_TYPE_8: return sdsheader8(s)->alloc - sdsheader8(s)->len;
        case SDS_TYPE_16: return sdsheader16(s)->alloc - sdsheader16(s)->len;
        case SDS_TYPE_32: return sdsheader32(s)->alloc - sdsheader32(s)->len;
        case SDS_TYPE_64: return sdsheader64(s)->alloc - sdsheader64(s)->len;
        default: return 0;
    }
}

/* 创建新SDS(从C字符串) */
sds sdsnew(const char *init) {
    return sdsnewlen(init, init ? strlen(init) : 0);
}

/* 创建新SDS(从二进制数据) */
sds sdsnewlen(const void *init, size_t initlen) {
    sds s;
    struct sdshdr8 *sh;
    size_t hdrlen;
    unsigned char type = sdsReqType(initlen);

    hdrlen = sdsHdrSize(type);
    s = malloc(hdrlen + initlen + 1);
    if (!s) return NULL;

    sh = (struct sdshdr8 *)s;
    s = (char *)s + hdrlen;

    switch(type) {
        case SDS_TYPE_5:
            *((uint8_t *)sh) = (uint8_t)((initlen << 3) | SDS_TYPE_5);
            break;
        case SDS_TYPE_8:
            sh->len = initlen;
            sh->alloc = initlen;
            sh->flags = type;
            break;
        // ... 其他类型类似
    }

    if (initlen && init) {
        memcpy(s, init, initlen);
    }
    s[initlen] = '\0';

    return s;
}

/* 追加字符串(核心优化:预分配空间,减少内存分配次数) */
sds sdscatlen(sds s, const void *t, size_t len) {
    size_t curlen = sdslen(s);
    s = sdsMakeRoomFor(s, len);
    if (!s) return NULL;

    memcpy(s + curlen, t, len);
    s[curlen + len] = '\0';
    sdslen(s) = curlen + len;
    return s;
}

/* 空间预分配策略(Redis经典策略) */
sds sdsMakeRoomFor(sds s, size_t addlen) {
    size_t avail = sdsavail(s);
    if (avail >= addlen) return s;

    size_t newlen = sdslen(s) + addlen;
    size_t hdrlen = sdsHdrSize(sdsflags(s));
    char *newsh;

    /* 核心策略:小于1MB时翻倍扩容,大于1MB时每次增加1MB */
    if (newlen < SDS_MAX_PREALLOC) {
        newlen *= 2;
    } else {
        newlen += SDS_MAX_PREALLOC;
    }

    unsigned char newtype = sdsReqType(newlen);
    if (newtype == SDS_TYPE_5) newtype = SDS_TYPE_8;

    size_t newhdrlen = sdsHdrSize(newtype);

    if (newtype == sdsflags(s)) {
        newsh = realloc(s - hdrlen, newhdrlen + newlen + 1);
        if (!newsh) return NULL;
        s = newsh + hdrlen;
    } else {
        // 类型变化,需要重新分配并拷贝
        newsh = malloc(newhdrlen + newlen + 1);
        if (!newsh) return NULL;
        memcpy(newsh + newhdrlen, s, curlen + 1);
        free(s - hdrlen);
        s = newsh + newhdrlen;
    }

    // 更新头部信息
    // ...
    return s;
}

3.2 高性能哈希表实现
哈希表是缓存系统的核心数据结构。C-Cache实现了渐进式哈希表,解决单次扩容导致的服务卡顿问题。

// src/datastore/dict.h
#ifndef CCACHE_DICT_H
#define CCACHE_DICT_H

#include <stdint.h>
#include "sds.h"

/* 哈希函数类型 */
typedef uint64_t (*dictHashFunction)(const void *key, size_t len);

/* 键值对 */
typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
    } v;
    struct dictEntry *next;  // 链地址法解决冲突
} dictEntry;

/* 字典类型(多态操作) */
typedef struct dictType {
    uint64_t (*hashFunction)(const void *key, size_t len);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} dictType;

/* 哈希表(一个字典有两个哈希表,用于渐进式rehash) */
typedef struct dictht {
    dictEntry **table;      // 哈希桶数组
    unsigned long size;     // 哈希表大小
    unsigned long sizemask; // 用于计算索引的掩码(size-1)
    unsigned long used;     // 已使用节点数
} dictht;

/* 字典主结构 */
typedef struct dict {
    dictType *type;          // 类型特定函数
    void *privdata;          // 私有数据
    dictht ht[2];            // 两个哈希表(ht[1]用于rehash)
    int rehashidx;           // rehash进度(-1表示未进行)
    int iterators;           // 当前运行的迭代器数量
} dict;

/* 迭代器 */
typedef struct dictIterator {
    dict *d;
    int table;               // 当前遍历的哈希表索引(0或1)
    int index;               // 当前桶索引
    int safe;                // 是否安全迭代器(允许修改)
    dictEntry *entry;        // 当前节点
    dictEntry *nextEntry;    // 下一个节点
} dictIterator;

/* API声明 */
dict *dictCreate(dictType *type, void *privdata);
int dictExpand(dict *d, unsigned long size);
int dictRehash(dict *d, int n);
int dictAdd(dict *d, void *key, void *val);
dictEntry *dictFind(dict *d, const void *key);
void *dictFetchValue(dict *d, const void *key);
int dictDelete(dict *d, const void *key);
void dictRelease(dict *d);
dictIterator *dictGetIterator(dict *d);
dictEntry *dictNext(dictIterator *iter);
void dictReleaseIterator(dictIterator *iter);

#endif
j// src/datastore/dict.c - 核心实现
#include "dict.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/* 初始哈希表大小 */
#define DICT_HT_INITIAL_SIZE 4

/* 哈希表扩容因子(used >= size时触发扩容)*/
#define DICT_HT_EXPAND_FACTOR 1

/* 缩容因子(used < size * 0.1时触发缩容)*/
#define DICT_HT_SHRINK_FACTOR 10

/* 创建字典 */
dict *dictCreate(dictType *type, void *privdata) {
    dict *d = malloc(sizeof(dict));
    if (!d) return NULL;

    d->type = type;
    d->privdata = privdata;
    d->rehashidx = -1;
    d->iterators = 0;
    d->ht[0] = (dictht){ NULL, 0, 0, 0 };
    d->ht[1] = (dictht){ NULL, 0, 0, 0 };

    if (dictExpand(d, DICT_HT_INITIAL_SIZE) != 0) {
        free(d);
        return NULL;
    }

    return d;
}

/* 扩容/缩容核心函数 */
int dictExpand(dict *d, unsigned long size) {
    // 如果正在rehash,不能再次扩容
    if (d->rehashidx != -1) return -1;

    // 确保size是2的幂
    unsigned long realsize = DICT_HT_INITIAL_SIZE;
    while (realsize < size) realsize <<= 1;

    // 创建新哈希表
    dictht n = { NULL, realsize, realsize - 1, 0 };
    n.table = calloc(realsize, sizeof(dictEntry*));
    if (!n.table) return -1;

    // 如果当前哈希表为空,直接使用新表
    if (d->ht[0].table == NULL) {
        d->ht[0] = n;
        return 0;
    }

    // 否则设置ht[1]为新表,启动渐进式rehash
    d->ht[1] = n;
    d->rehashidx = 0;
    return 0;
}

/* 渐进式rehash(核心:分步迁移,避免单次卡顿)*/
int dictRehash(dict *d, int n) {
    // 空转保护
    if (d->rehashidx == -1) return 0;

    int empty_visits = n * 10;  // 最多跳过10*n个空桶
    while (n-- && d->ht[0].used != 0) {
        // 跳过空桶(最多跳过empty_visits次)
        while (d->ht[0].table[d->rehashidx] == NULL) {
            d->rehashidx++;
            if (--empty_visits == 0) return 1;
        }

        // 迁移当前桶的所有节点
        dictEntry *de = d->ht[0].table[d->rehashidx];
        while (de) {
            dictEntry *next = de->next;

            // 计算在新表中的索引
            unsigned long h = dictHashKey(d, de->key) & d->ht[1].sizemask;
            de->next = d->ht[1].table[h];
            d->ht[1].table[h] = de;

            d->ht[0].used--;
            d->ht[1].used++;
            de = next;
        }
        d->ht[0].table[d->rehashidx] = NULL;
        d->rehashidx++;
    }

    // 检查rehash是否完成
    if (d->ht[0].used == 0) {
        free(d->ht[0].table);
        d->ht[0] = d->ht[1];
        d->ht[1] = (dictht){ NULL, 0, 0, 0 };
        d->rehashidx = -1;
        return 0;
    }

    return 1;
}

/* 在rehash过程中查找键 */
dictEntry *dictFind(dict *d, const void *key) {
    // 如果正在rehash,执行一步rehash(每次查找都推进)
    if (d->rehashidx != -1) {
        dictRehash(d, 1);
    }

    unsigned long h = dictHashKey(d, key);
    // 先在ht[0]查找
    dictEntry *de = d->ht[0].table[h & d->ht[0].sizemask];
    while (de) {
        if (dictCompareKeys(d, key, de->key)) return de;
        de = de->next;
    }

    // 如果正在rehash,再到ht[1]查找
    if (d->rehashidx != -1) {
        de = d->ht[1].table[h & d->ht[1].sizemask];
        while (de) {
            if (dictCompareKeys(d, key, de->key)) return de;
            de = de->next;
        }
    }

    return NULL;
}

/* 添加键值对 */
int dictAdd(dict *d, void *key, void *val) {
    // 检查是否需要扩容
    if (d->ht[0].used >= d->ht[0].size && d->rehashidx == -1) {
        dictExpand(d, d->ht[0].used * 2);
    }

    // 如果正在rehash,推进
    if (d->rehashidx != -1) dictRehash(d, 1);

    // 计算哈希值
    unsigned long h = dictHashKey(d, key);
    int table = d->rehashidx != -1 ? 1 : 0;
    unsigned long idx = h & d->ht[table].sizemask;

    // 检查键是否已存在
    dictEntry *de = d->ht[table].table[idx];
    while (de) {
        if (dictCompareKeys(d, key, de->key)) return -1;
        de = de->next;
    }

    // 创建新节点
    de = malloc(sizeof(dictEntry));
    if (!de) return -1;

    de->key = dictDupKey(d, key);
    de->v.val = dictDupVal(d, val);
    de->next = d->ht[table].table[idx];
    d->ht[table].table[idx] = de;
    d->ht[table].used++;

    return 0;
}

3.3 内存分配器封装

// src/utils/alloc.h
#ifndef CCACHE_ALLOC_H
#define CCACHE_ALLOC_H

#include <stddef.h>

/* 内存分配器接口(支持jemalloc、tcmalloc或系统malloc)*/
void *zmalloc(size_t size);
void *zcalloc(size_t size);
void *zrealloc(void *ptr, size_t size);
void zfree(void *ptr);
char *zstrdup(const char *s);
size_t zmalloc_used_memory(void);
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
void zmalloc_enable_thread_safeness(void);

#endif
// src/utils/alloc.c
#include "alloc.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#ifdef USE_JEMALLOC
#include <jemalloc/jemalloc.h>
#define malloc je_malloc
#define calloc je_calloc
#define realloc je_realloc
#define free je_free
#endif

/* 内存使用统计(原子操作) */
static size_t used_memory = 0;
static pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;

/* OOM处理函数 */
static void (*oom_handler)(size_t) = NULL;

void *zmalloc(size_t size) {
    void *ptr = malloc(size);
    if (!ptr) {
        if (oom_handler) oom_handler(size);
        return NULL;
    }

    pthread_mutex_lock(&used_memory_mutex);
    used_memory += size;
    pthread_mutex_unlock(&used_memory_mutex);

    return ptr;
}

void *zcalloc(size_t size) {
    void *ptr = calloc(1, size);
    if (!ptr) {
        if (oom_handler) oom_handler(size);
        return NULL;
    }

    pthread_mutex_lock(&used_memory_mutex);
    used_memory += size;
    pthread_mutex_unlock(&used_memory_mutex);

    return ptr;
}

void *zrealloc(void *ptr, size_t size) {
    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
    void *newptr = realloc(ptr, size);
    if (!newptr && size > 0) {
        if (oom_handler) oom_handler(size);
        return NULL;
    }

    pthread_mutex_lock(&used_memory_mutex);
    used_memory -= old_size;
    used_memory += size;
    pthread_mutex_unlock(&used_memory_mutex);

    return newptr;
}

void zfree(void *ptr) {
    if (!ptr) return;

    size_t old_size = malloc_usable_size(ptr);
    pthread_mutex_lock(&used_memory_mutex);
    used_memory -= old_size;
    pthread_mutex_unlock(&used_memory_mutex);

    free(ptr);
}

size_t zmalloc_used_memory(void) {
    size_t mem;
    pthread_mutex_lock(&used_memory_mutex);
    mem = used_memory;
    pthread_mutex_unlock(&used_memory_mutex);
    return mem;
}

来源:
https://xcfsr.cn/category/software-dev.html

相关文章
|
2月前
|
缓存 NoSQL Redis
C语言企业项目实战(一)
教程来源 https://xcfsr.cn/ 本文以高性能内存缓存系统C-Cache为实战案例,完整呈现C语言在企业级开发中的工程化实践:涵盖需求分析、架构设计(事件驱动+多线程)、内存管理、Redis协议兼容实现、持久化与主从复制等,助你掌握百万行代码级C项目的核心能力。
|
2月前
|
存储 缓存 人工智能
大模型应用:快速搭建轻量级智能体:从模型下载到图文输出简单实践.75
本文介绍如何用轻量级Qwen1.5-1.8B-Chat模型(单卡4G显存或CPU即可运行)搭建本地智能体:从高速下载缓存、文本对话交互,到解析用户指令生成绘图参数,并用Pillow绘制文字海报、几何图形、渐变/抽象艺术图,全程代码清晰、开箱即用,适合大模型入门实操。
371 7
|
3月前
|
传感器 存储 安全
嵌入式进阶指南:从“代码搬运工”到“系统架构师”的跃迁之路
教程来源 https://app-a87ujc988w01.appmiaoda.com/ 《嵌入式进阶指南》助力开发者从“代码搬运工”跃升为“系统架构师”。涵盖性能调优、RTOS内核剖析、嵌入式安全、系统架构设计及功耗管理五大核心维度,融合RISC-V、TinyML等前沿趋势,提供实战路径与深度原理。
|
3月前
|
人工智能 运维 API
OpenClaw阿里云+本地三系统部署与商业变现完整指南:大模型配置+避坑指南
OpenClaw(曾用名:Clawdbot)作为一款开源、本地优先、可长期稳定运行的AI智能体执行网关,凭借自动化任务处理、多模型兼容、技能扩展与24小时无人值守能力,成为个人低成本启动商业变现的首选工具。无需大额资金投入,无需组建团队,个人可通过技术服务、数字产品、自动化代运营、技能开发、内容付费、跨境接单、企业定制等多元路径,将AI能力转化为持续收益。
438 5
|
3月前
|
Java 测试技术 开发者
Spring学习知识点大全(一)
教程来源 https://app-abdss1rim1oh.appmiaoda.com Spring是Java企业级开发的事实标准框架,以轻量、非侵入和强大DI/AOP为核心,涵盖IoC容器、AOP、数据访问、Web及测试等全栈能力。本文系统梳理其基础概念、Bean管理、依赖注入与生命周期等核心知识,助力初学者构建体系,赋能开发者深入进阶。
|
3月前
|
消息中间件 NoSQL Linux
嵌入式开发新手入门教程(第二卷)
教程来源 https://app-a7illrp9pngh.appmiaoda.com/ 本课程系统讲解嵌入式软件设计核心知识:涵盖嵌入式C编程、Linux开发、系统编程与设备驱动;前瞻边缘智能(TinyML)、RISC-V架构及工具链演进趋势;强调“硬件→裸机→RTOS→Linux”渐进路径与动手实践,助你夯实基础、迈向万物互联。
|
3月前
|
传感器 机器人 Linux
嵌入式开发新手入门教程(第一卷)
教程来源 https://app-a6nw7st4g741.appmiaoda.com/ 嵌入式系统是嵌入设备内部的专用计算机系统,广泛应用于智能手表、汽车电控、医疗设备乃至火星车等。其由硬件(MCU、存储器、外设)和软件(裸机/RTOS/嵌入式Linux)构成。新手可按电路与C语言→单片机开发→RTOS与ARM深入三阶段学习,推荐STM32平台入门。
|
2月前
|
人工智能 弹性计算 关系型数据库
阿里云企业新用户定义及专属优惠政策解读
阿里云面向企业新用户推出多重专属优惠:需完成企业实名认证、无历史付费记录、同一主体仅享一次。涵盖38元/年起的轻量服务器、199元/年u1实例、5亿算力补贴、最高4万元AI抵扣金及10万元出海资源包,助力中小企业降本增效、快速上云。
266 12
|
2月前
|
安全 JavaScript 前端开发
React2Shell 漏洞自动化凭证窃取攻击机理与防御研究
CVE-2025-55182(React2Shell)是CVSS 10.0的高危RCE漏洞,可无认证、无交互远程接管Next.js等RSC应用服务器。2026年已爆发规模化自动化凭证窃取攻击,单日入侵766台服务器。本文系统剖析漏洞机理与攻击链,构建检测、监控、防御、响应一体化闭环体系,提供可落地的代码与方案。(239字)
255 16