TEE-TA学习轨迹第九篇:libteec代码详细分析
libteec代码详细分析libteec.so是TEETrusted Execution Environment可信执行环境客户端API的核心实现遵循GlobalPlatformGPTEE标准主要用于Linux用户空间REE富执行环境与安全世界的TEE如OP-TEE进行通信提供会话管理、共享内存操作、命令调用等核心能力。一、代码整体背景1. 版权与许可代码由Linaro维护基于BSD许可开源适配OP-TEEOpen Portable TEE是连接普通应用与TEE安全服务的关键层。2. 核心依赖系统调用fcntl文件控制、ioctl设备控制、mmap内存映射、pthread线程安全等TEE标准头文件tee_client_api.hGP TEE客户端API定义、linux/tee.hLinux内核TEE驱动接口调试/日志teec_trace.hTEEC日志宏如EMSG。二、关键宏与常量定义宏/常量用途__aligned(x)封装编译器的内存对齐属性__attribute__((aligned(x)))MIN(x,y)取两个值的最小值TEEC_MAX_DEV_SEQ尝试打开TEE设备文件的最大序列遍历/dev/tee0到/dev/tee9MEMREF_SHM_ID/Offs/Size操作struct tee_ioctl_param中内存引用的SHM ID、偏移、大小字段SHM_FLAG_*共享内存内部标志BUFFER_ALLOCED缓冲区已分配SHADOW_BUFFER_ALLOCED影子缓冲区已分配三、静态辅助函数工具层1. 线程安全锁封装static void teec_mutex_lock(pthread_mutex_t *mu) { pthread_mutex_lock(mu); } static void teec_mutex_unlock(pthread_mutex_t *mu) { pthread_mutex_unlock(mu); }封装pthread互斥锁的加/解锁保证多线程访问TEE资源时的安全性。2. 内存分配页对齐分配static void *teec_paged_aligned_alloc(size_t sz) { void *p NULL; size_t page_sz sysconf(_SC_PAGESIZE); // 获取系统页大小 size_t aligned_sz ((sz page_sz - 1) / page_sz) * page_sz; // 向上取整到页大小 if (aligned_sz sz !posix_memalign(p, page_sz, aligned_sz)) return p; return NULL; }按系统页大小对齐分配内存TEE共享内存要求页对齐避免内存对齐导致的访问错误。3. 设备打开验证TEE兼容性static int teec_open_dev(const char *devname, const char *capabilities, uint32_t *gen_caps) { int fd 0; struct tee_ioctl_version_data vers; memset(vers, 0, sizeof(vers)); fd open(devname, O_RDWR); if (fd 0) return -1; if (ioctl(fd, TEE_IOC_VERSION, vers)) { EMSG(TEE_IOC_VERSION failed); goto err; } /* We can only handle GP TEEs */ if (!(vers.gen_caps TEE_GEN_CAP_GP)) goto err; if (capabilities) { if (strcmp(capabilities, optee-tz) 0) { if (vers.impl_id ! TEE_IMPL_ID_OPTEE) goto err; if (!(vers.impl_caps TEE_OPTEE_CAP_TZ)) goto err; } else { /* Unrecognized capability requested */ goto err; } } *gen_caps vers.gen_caps; return fd; err: close(fd); return -1; }打开TEE设备文件如/dev/tee0通过TEE_IOC_VERSION ioctl验证必须是GPGlobalPlatform兼容的TEE若指定capabilitiesoptee-tz需验证是OP-TEE实现且支持TZTrusted Zone返回设备FD和TEE通用能力gen_caps。4. 共享内存分配/注册static int teec_shm_alloc(int fd, size_t size, int *id); // 向TEE申请分配共享内存 static intstatic int teec_shm_alloc(int fd, size_t size, int *id) { int shm_fd 0; struct tee_ioctl_shm_alloc_data data; memset(data, 0, sizeof(data)); data.size size; shm_fd ioctl(fd, TEE_IOC_SHM_ALLOC, data); if (shm_fd 0) return -1; *id data.id; return shm_fd; }teec_shm_register(int fd, void *buf, size_t size, int *id); // 注册用户内存到TEEstatic int teec_shm_register(int fd, void *buf, size_t size, int *id) { int shm_fd 0; struct tee_ioctl_shm_register_data data; memset(data, 0, sizeof(data)); data.addr (uintptr_t)buf; data.length size; shm_fd ioctl(fd, TEE_IOC_SHM_REGISTER, data); if (shm_fd 0) return -1; *id data.id; return shm_fd; }通过TEE_IOC_SHM_ALLOC/TEE_IOC_SHM_REGISTER ioctl与TEE内核交互返回共享内存FD和ID。四、核心API实现GP标准接口1. 上下文管理初始化/销毁TEEC_InitializeContextTEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *ctx)TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *ctx) { char devname[PATH_MAX] { 0 }; int fd 0; size_t n 0; if (!ctx) return TEEC_ERROR_BAD_PARAMETERS; for (n 0; n TEEC_MAX_DEV_SEQ; n) { uint32_t gen_caps 0; snprintf(devname, sizeof(devname), /dev/tee%zu, n); fd teec_open_dev(devname, name, gen_caps); if (fd 0) { ctx-imp.fd fd; ctx-imp.reg_mem gen_caps TEE_GEN_CAP_REG_MEM; ctx-imp.memref_null gen_caps TEE_GEN_CAP_MEMREF_NULL; return TEEC_SUCCESS; } } return TEEC_ERROR_ITEM_NOT_FOUND; }功能初始化TEE上下文与TEE设备建立连接逻辑遍历/dev/tee0到/dev/tee9调用teec_open_dev打开兼容的TEE设备记录设备FD、TEE能力如是否支持注册内存、空内存引用失败返回TEEC_ERROR_ITEM_NOT_FOUND无可用TEE设备。TEEC_FinalizeContextvoid TEEC_FinalizeContext(TEEC_Context *ctx)void TEEC_FinalizeContext(TEEC_Context *ctx) { if (ctx) close(ctx-imp.fd); }功能销毁TEE上下文关闭设备FD。2. 共享内存管理TEEC_AllocateSharedMemoryTEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) { int fd 0; size_t s 0; if (!ctx || !shm) return TEEC_ERROR_BAD_PARAMETERS; if (!shm-flags || (shm-flags ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) return TEEC_ERROR_BAD_PARAMETERS; s shm-size; if (!s) s 8; if (ctx-imp.reg_mem) { shm-buffer teec_paged_aligned_alloc(s); if (!shm-buffer) return TEEC_ERROR_OUT_OF_MEMORY; fd teec_shm_register(ctx-imp.fd, shm-buffer, s, shm-imp.id); if (fd 0) { free(shm-buffer); shm-buffer NULL; return TEEC_ERROR_OUT_OF_MEMORY; } shm-imp.registered_fd fd; } else { fd teec_shm_alloc(ctx-imp.fd, s, shm-imp.id); if (fd 0) return TEEC_ERROR_OUT_OF_MEMORY; shm-buffer mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (shm-buffer (void *)MAP_FAILED) { shm-imp.id -1; return TEEC_ERROR_OUT_OF_MEMORY; } shm-imp.registered_fd -1; } shm-imp.shadow_buffer NULL; shm-imp.alloced_size s; shm-imp.flags SHM_FLAG_BUFFER_ALLOCED; return TEEC_SUCCESS; }功能由TEE内核分配共享内存而非用户提供逻辑按页对齐分配内存注册到TEE若TEE不支持注册内存通过mmap映射TEE分配的内存到用户空间。TEEC_ReleaseSharedMemoryvoid TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shm)功能释放共享内存清理影子缓冲区/映射内存关闭FD重置元信息。TEEC_RegisterSharedMemoryTEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) { TEEC_Result res TEEC_SUCCESS; int fd 0; size_t s 0; if (!ctx || !shm) return TEEC_ERROR_BAD_PARAMETERS; if (!shm-flags || (shm-flags ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) return TEEC_ERROR_BAD_PARAMETERS; if (!shm-buffer) return TEEC_ERROR_BAD_PARAMETERS; s shm-size; if (!s) s 8; if (ctx-imp.reg_mem) { fd teec_shm_register(ctx-imp.fd, shm-buffer, s, shm-imp.id); if (fd 0) { shm-imp.registered_fd fd; shm-imp.shadow_buffer NULL; shm-imp.flags 0; goto out; } /* * If were here TEE_IOC_SHM_REGISTER failed, probably * because some read-only memory was supplied and the Linux * kernel doesnt like that at the moment. * * The error could also have some other origin. In any case * were not making matters worse by trying to allocate and * register a shadow buffer before giving up. */ shm-imp.shadow_buffer teec_paged_aligned_alloc(s); if (!shm-imp.shadow_buffer) return TEEC_ERROR_OUT_OF_MEMORY; fd teec_shm_register(ctx-imp.fd, shm-imp.shadow_buffer, s, shm-imp.id); if (fd 0) { shm-imp.registered_fd fd; shm-imp.flags SHM_FLAG_SHADOW_BUFFER_ALLOCED; goto out; } if (errno ENOMEM) res TEEC_ERROR_OUT_OF_MEMORY; else res TEEC_ERROR_GENERIC; free(shm-imp.shadow_buffer); shm-imp.shadow_buffer NULL; return res; } else { fd teec_shm_alloc(ctx-imp.fd, s, shm-imp.id); if (fd 0) return TEEC_ERROR_OUT_OF_MEMORY; shm-imp.shadow_buffer mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (shm-imp.shadow_buffer (void *)MAP_FAILED) { shm-imp.id -1; return TEEC_ERROR_OUT_OF_MEMORY; } shm-imp.registered_fd -1; shm-imp.flags 0; } out: shm-imp.alloced_size s; return TEEC_SUCCESS; }功能将用户空间的内存注册到TEE供安全世界访问关键逻辑校验参数上下文/共享内存非空、标志合法、缓冲区非空若TEE支持内存注册reg_mem直接注册用户内存若注册失败如用户内存只读分配影子缓冲区可写注册影子缓冲区并拷贝用户数据记录共享内存ID、FD、影子缓冲区等元信息。3. 会话管理TEEC_OpenSessionTEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session, const TEEC_UUID *destination, uint32_t connection_method, const void *connection_data, TEEC_Operation *operation, uint32_t *ret_origin) { struct tee_ioctl_open_session_arg *arg NULL; struct tee_ioctl_param *params NULL; TEEC_Result res TEEC_ERROR_GENERIC; uint32_t eorig 0; int rc 0; const size_t arg_size sizeof(struct tee_ioctl_open_session_arg) TEEC_CONFIG_PAYLOAD_REF_COUNT * sizeof(struct tee_ioctl_param); union { struct tee_ioctl_open_session_arg arg; uint8_t data[arg_size]; } buf; struct tee_ioctl_buf_data buf_data; TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; memset(buf, 0, sizeof(buf)); memset(shm, 0, sizeof(shm)); memset(buf_data, 0, sizeof(buf_data)); if (!ctx || !session) { eorig TEEC_ORIGIN_API; res TEEC_ERROR_BAD_PARAMETERS; goto out; } buf_data.buf_ptr (uintptr_t)buf; buf_data.buf_len sizeof(buf); arg buf.arg; arg-num_params TEEC_CONFIG_PAYLOAD_REF_COUNT; params (struct tee_ioctl_param *)(arg 1); uuid_to_octets(arg-uuid, destination); setup_client_data(arg, connection_method, connection_data); res teec_pre_process_operation(ctx, operation, params, shm); if (res ! TEEC_SUCCESS) { eorig TEEC_ORIGIN_API; goto out_free_temp_refs; } rc ioctl(ctx-imp.fd, TEE_IOC_OPEN_SESSION, buf_data); if (rc) { EMSG(TEE_IOC_OPEN_SESSION failed); eorig TEEC_ORIGIN_COMMS; res ioctl_errno_to_res(errno); goto out_free_temp_refs; } res arg-ret; eorig arg-ret_origin; if (res TEEC_SUCCESS) { session-imp.ctx ctx; session-imp.session_id arg-session; } teec_post_process_operation(operation, params, shm); out_free_temp_refs: teec_free_temp_refs(operation, shm); out: if (ret_origin) *ret_origin eorig; return res; }功能与TEE中的可信应用TA建立会话核心步骤构造tee_ioctl_open_session_arg参数TA的UUID、客户端登录方式、参数列表预处理操作参数转换为TEE内核可识别的格式见下文参数处理通过TEE_IOC_OPEN_SESSION ioctl发送会话打开请求后处理参数将TEE返回的数据拷贝回用户空间记录会话ID返回执行结果。TEEC_CloseSessionvoid TEEC_CloseSession(TEEC_Session *session) { struct tee_ioctl_close_session_arg arg; memset(arg, 0, sizeof(arg)); if (!session) return; arg.session session-imp.session_id; if (ioctl(session-imp.ctx-imp.fd, TEE_IOC_CLOSE_SESSION, arg)) EMSG(Failed to close session 0x%x, session-imp.session_id); }功能关闭TEE会话通过TEE_IOC_CLOSE_SESSION ioctl通知TEE内核。4. 命令调用TEEC_InvokeCommandTEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id, TEEC_Operation *operation, uint32_t *error_origin) { struct tee_ioctl_invoke_arg *arg NULL; struct tee_ioctl_param *params NULL; TEEC_Result res TEEC_ERROR_GENERIC; uint32_t eorig 0; int rc 0; const size_t arg_size sizeof(struct tee_ioctl_invoke_arg) TEEC_CONFIG_PAYLOAD_REF_COUNT * sizeof(struct tee_ioctl_param); union { struct tee_ioctl_invoke_arg arg; uint8_t data[arg_size]; } buf; struct tee_ioctl_buf_data buf_data; TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; memset(buf, 0, sizeof(buf)); memset(buf_data, 0, sizeof(buf_data)); memset(shm, 0, sizeof(shm)); if (!session) { eorig TEEC_ORIGIN_API; res TEEC_ERROR_BAD_PARAMETERS; goto out; } buf_data.buf_ptr (uintptr_t)buf; buf_data.buf_len sizeof(buf); arg buf.arg; arg-num_params TEEC_CONFIG_PAYLOAD_REF_COUNT; params (struct tee_ioctl_param *)(arg 1); arg-session session-imp.session_id; arg-func cmd_id; if (operation) { teec_mutex_lock(teec_mutex); operation-imp.session session; teec_mutex_unlock(teec_mutex); } res teec_pre_process_operation(session-imp.ctx, operation, params, shm); if (res ! TEEC_SUCCESS) { eorig TEEC_ORIGIN_API; goto out_free_temp_refs; } rc ioctl(session-imp.ctx-imp.fd, TEE_IOC_INVOKE, buf_data); if (rc) { EMSG(TEE_IOC_INVOKE failed); eorig TEEC_ORIGIN_COMMS; res ioctl_errno_to_res(errno); goto out_free_temp_refs; } res arg-ret; eorig arg-ret_origin; teec_post_process_operation(operation, params, shm); out_free_temp_refs: teec_free_temp_refs(operation, shm); out: if (error_origin) *error_origin eorig; return res; }功能向已建立的TEE会话发送命令调用TA的接口逻辑构造tee_ioctl_invoke_arg参数会话ID、命令ID、参数列表预处理操作参数保证线程安全关联operation与session通过TEE_IOC_INVOKE ioctl发送命令后处理参数返回TEE的执行结果和错误来源。5. 操作取消TEEC_RequestCancellationvoid TEEC_RequestCancellation(TEEC_Operation *operation) { TEEC_Session *session NULL; struct tee_ioctl_cancel_arg arg; memset(arg, 0, sizeof(arg)); if (!operation) return; teec_mutex_lock(teec_mutex); session operation-imp.session; teec_mutex_unlock(teec_mutex); if (!session) return; arg.session session-imp.session_id; arg.cancel_id 0; if (ioctl(session-imp.ctx-imp.fd, TEE_IOC_CANCEL, arg)) EMSG(TEE_IOC_CANCEL: %s, strerror(errno)); }功能取消正在执行的TEE操作通过TEE_IOC_CANCEL ioctl通知TEE内核。五、参数处理TEE支持多种参数类型值参数、内存引用参数代码通过pre_process/post_process系列函数完成用户空间参数 ↔ TEE内核参数的转换1. 参数类型分类参数类型用途TEEC_NONE无参数TEEC_VALUE_*整型值参数输入/输出/输入输出TEEC_MEMREF_TEMP_*临时内存引用单次命令有效无需提前注册TEEC_MEMREF_WHOLE整段注册内存引用使用已注册的共享内存全部空间TEEC_MEMREF_PARTIAL_*部分注册内存引用使用已注册共享内存的指定偏移/大小2. 预处理teec_pre_process_*转换参数类型为TEE内核定义的tee_ioctl_param格式处理内存引用分配临时共享内存、拷贝用户数据到影子缓冲区校验参数合法性如偏移大小不超过共享内存范围。3. 后处理teec_post_process_*将TEE返回的结果如输出内存数据、值参数拷贝回用户空间更新用户传入的参数结构体如内存大小、值参数的a/b字段。4. 临时内存释放teec_free_temp_refs释放临时内存引用分配的共享内存避免内存泄漏。六、错误处理与辅助函数1. ioctl_errno_to_resstatic TEEC_Result ioctl_errno_to_res(int err)将系统调用错误码如ENOMEM、EINVAL转换为GP标准的TEEC错误码如TEEC_ERROR_OUT_OF_MEMORY、TEEC_ERROR_BAD_PARAMETERS。2. uuid_to_octetsstatic void uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], const TEEC_UUID *s)将TEEC_UUID结构体转换为TEE内核要求的字节数组格式。3. setup_client_datastatic void setup_client_data(struct tee_ioctl_open_session_arg *arg, uint32_t connection_method, const void *connection_data)设置客户端登录方式如公共登录、用户登录、组登录填充会话的客户端身份信息。七、核心功能总结该代码实现了GP TEE客户端API的核心能力主要解决以下需求TEE设备交互遍历并打开兼容的TEE设备验证TEE兼容性共享内存管理支持注册用户内存、分配TEE内存处理内存对齐和只读内存问题影子缓冲区会话生命周期与TA建立/关闭会话传递客户端身份信息命令调用向TA发送命令处理多类型参数的转换与数据拷贝线程安全通过互斥锁保证多线程访问TEE资源的安全性错误标准化将系统错误转换为GP标准错误码便于上层应用处理。八、典型使用流程1. TEEC_InitializeContext → 初始化TEE上下文 2. TEEC_AllocateSharedMemory/RegisterSharedMemory → 分配/注册共享内存 3. TEEC_OpenSession → 与TA建立会话 4. TEEC_InvokeCommand → 调用TA的命令传递参数、共享内存 5. TEEC_CloseSession → 关闭会话 6. TEEC_ReleaseSharedMemory → 释放共享内存 7. TEEC_FinalizeContext → 销毁上下文

相关新闻

React 与 Next.js 工程化实战:从服务端渲染到流式交互的性能全链路优化

React 与 Next.js 工程化实战:从服务端渲染到流式交互的性能全链路优化

React 与 Next.js 工程化实战:从服务端渲染到流式交互的性能全链路优化一、首屏白屏与交互卡顿:现代 Web 应用的性能瓶颈溯源 现代 Web 应用的用户体验瓶颈集中在两个维度:首屏加载速度与交互响应延迟。传统 CSR(客户端渲染&#…

2026/7/1 14:05:03阅读更多 →
终极图片格式转换指南:3分钟掌握Save Image as Type扩展

终极图片格式转换指南:3分钟掌握Save Image as Type扩展

终极图片格式转换指南:3分钟掌握Save Image as Type扩展 【免费下载链接】Save-Image-as-Type Save Image as Type is an chrome extension which add Save as PNG / JPG / WebP to the context menu of image. 项目地址: https://gitcode.com/gh_mirrors/sa/Save…

2026/7/1 14:05:03阅读更多 →
如何快速安装Nintendo Switch大气层系统:终极安全指南

如何快速安装Nintendo Switch大气层系统:终极安全指南

如何快速安装Nintendo Switch大气层系统:终极安全指南 【免费下载链接】Atmosphere-stable 大气层整合包系统稳定版 项目地址: https://gitcode.com/gh_mirrors/at/Atmosphere-stable 你是否想让你的Switch拥有更多可能性?大气层(Atmo…

2026/7/1 14:05:03阅读更多 →
如何永久保存QQ空间回忆?QZoneExport一键备份解决方案

如何永久保存QQ空间回忆?QZoneExport一键备份解决方案

如何永久保存QQ空间回忆?QZoneExport一键备份解决方案 【免费下载链接】QZoneExport QQ空间导出助手,用于备份QQ空间的说说、日志、私密日记、相册、视频、留言板、QQ好友、收藏夹、分享、最近访客为文件,便于迁移与保存 项目地址: https:/…

2026/7/1 15:10:15阅读更多 →
月薪还不到五千的苦逼牛马们,花大几千考PMP,是“人傻钱多”还是“人间清醒”?

月薪还不到五千的苦逼牛马们,花大几千考PMP,是“人傻钱多”还是“人间清醒”?

写在前面:一笔“算不清”的账 你是不是早就习惯了这样的日子? 早高峰地铁被人群挤着,午餐只敢选15元以内的套餐,工资到账先还花呗、交房租,扣完几乎没结余。盯着不足五千的月薪,天天琢磨怎么省钱&#xff…

2026/7/1 15:10:15阅读更多 →
如何在Windows上快速安装Android应用?APK Installer完全指南

如何在Windows上快速安装Android应用?APK Installer完全指南

如何在Windows上快速安装Android应用?APK Installer完全指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 想在Windows电脑上轻松安装Android应用吗&…

2026/7/1 15:10:15阅读更多 →
3步解锁QQ音乐解析:Python工具助你轻松获取无损音质与批量歌单

3步解锁QQ音乐解析:Python工具助你轻松获取无损音质与批量歌单

3步解锁QQ音乐解析:Python工具助你轻松获取无损音质与批量歌单 【免费下载链接】MCQTSS_QQMusic QQ音乐解析 项目地址: https://gitcode.com/gh_mirrors/mc/MCQTSS_QQMusic 你是否曾因音乐平台的限制而无法下载心仪歌曲?是否想建立个人音乐库却苦…

2026/7/1 15:10:15阅读更多 →
【轨物方案】清检一体化系统架构设计与关键创新:从单功能到多智能体协同

【轨物方案】清检一体化系统架构设计与关键创新:从单功能到多智能体协同

本系列第一篇分析了光伏运维的三大痛点——积灰损失、组件隐性缺陷、柔性支架安全盲区——以及现有纯清洁方案、机械协同方案和分离式检测方案各自的局限。这些局限共同指向一个方向:必须在同一机器人平台上实现清洁与巡检的物理融合。 本文将展开清检一体化方案的系…

2026/7/1 15:10:15阅读更多 →
从零开始!用Python打造你的第一个Agent,小白也能轻松收藏学习大模型原理

从零开始!用Python打造你的第一个Agent,小白也能轻松收藏学习大模型原理

很多人第一次接触 Agent,是从 LangChain、CrewAI、AutoGen 开始。框架文档里 Chain、Tool、Memory、Planner 一堆抽象,很容易让人觉得:Agent 很复杂,必须先学框架。 其实把框架剥开,底层逻辑就三件事:LLM 负…

2026/7/1 15:05:15阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/1 4:42:14阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/1 5:19:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →