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

相关文章
|
6天前
|
人工智能 JSON 监控
Claude Code 源码泄露:一份价值亿元的 AI 工程公开课
我以为顶级 AI 产品的护城河是模型。读完这 51.2 万行泄露的源码,我发现自己错了。
4333 17
|
17天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
14942 138
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
5天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
3104 8
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
7天前
|
人工智能 自然语言处理 数据挖掘
零基础30分钟搞定 Claude Code,这一步90%的人直接跳过了
本文直击Claude Code使用痛点,提供零基础30分钟上手指南:强调必须配置“工作上下文”(about-me.md+anti-ai-style.md)、采用Cowork/Code模式、建立标准文件结构、用提问式提示词驱动AI理解→规划→执行。附可复制模板与真实项目启动法,助你将Claude从聊天工具升级为高效执行系统。
|
6天前
|
人工智能 定位技术
Claude Code源码泄露:8大隐藏功能曝光
2026年3月,Anthropic因配置失误致Claude Code超51万行源码泄露,意外促成“被动开源”。代码中藏有8大未发布功能,揭示其向“超级智能体”演进的完整蓝图,引发AI编程领域震动。(239字)
2456 9