从ls -l到stat函数:深入Linux文件系统元数据获取与格式化
1. 项目概述从ls -l到stat的深度探索如果你在Linux命令行下待过一段时间那么ls -l这个命令一定是你最熟悉的老朋友之一。它列出的那一长串信息——文件权限、链接数、所有者、所属组、大小、修改时间——几乎是每个系统管理员和开发者日常诊断问题的起点。但你是否曾停下来想过这一行行简洁却信息量巨大的输出底层究竟是如何被“组装”出来的今天我们不满足于仅仅使用这个命令而是要亲手揭开它的神秘面纱通过模拟实现ls -l的核心功能来深入理解Linux文件系统的元数据管理。这个项目的核心就是stat函数族。ls -l命令的华丽外表之下本质是调用了stat()、lstat()或fstat()这些系统调用从文件的inode索引节点中提取出所有元数据信息。我们的任务就是绕过ls命令这个“黑盒”直接使用stat函数获取这些原始数据然后按照ls -l的经典格式将它们格式化输出。这不仅仅是一个编程练习更是一次对Linux文件系统核心概念的深度游。你会彻底弄明白文件权限位rwx的数字和符号表示法如何转换、时间戳如何从秒数变成人类可读的日期、以及如何区分不同类型的文件普通文件、目录、符号链接等。对于想深入系统编程、理解操作系统如何管理文件的开发者来说这是一个绝佳的入门和深化项目。2. 核心思路与设计拆解2.1 目标分析ls -l输出到底包含了什么在动手之前我们必须先像一个侦探一样仔细剖析ls -l的输出。一个典型的输出行如下-rwxr-xr-x 1 alice developers 20480 Jun 15 10:30 my_script.sh我们可以将其分解为以下几个字段文件类型与权限10个字符第一个字符表示文件类型-普通文件d目录l符号链接等后9个字符是三组所有者、组用户、其他用户的rwx权限。硬链接数表示有多少个目录项指向同一个inode。所有者名称文件所有者的用户名。所属组名称文件所属组的组名。文件大小字节文件内容的字节数。对于目录这个值通常是其目录项所占用的空间。最后修改时间文件内容最后一次被修改的时间通常以“月 日 时:分”的格式显示。如果文件修改时间距离现在超过6个月则会显示“月 日 年”。文件名文件或目录的名称。我们的模拟程序核心目标就是获取上述第1到第6项信息并按照这个格式进行排版输出。2.2 技术选型为什么是stat函数族在C语言中获取文件元数据主要有三个函数int stat(const char *pathname, struct stat *statbuf);int lstat(const char *pathname, struct stat *statbuf);int fstat(int fd, struct stat *statbuf);它们都填充一个struct stat结构体但行为有细微差别stat()追踪符号链接。如果pathname是一个符号链接它返回的是链接指向的目标文件的元数据。lstat()不追踪符号链接。返回符号链接文件本身的元数据。这对于判断一个文件是否是符号链接至关重要。fstat()通过已打开的文件描述符fd来获取元数据。为什么我们主要使用lstat因为一个真实的ls -l命令当列出一个符号链接时它显示的是链接本身的信息类型为l而不是其目标的信息。只有当你使用ls -lL跟随链接时它才会像stat()那样行为。因此为了准确模拟默认的ls -l我们应该优先使用lstat()。struct stat结构体包含了我们需要的几乎所有信息例如st_mode类型和权限、st_nlink链接数、st_uid/st_gid所有者和组ID、st_size大小、st_mtime修改时间等。2.3 整体架构设计我们的模拟程序可以遵循以下清晰的流程参数解析处理命令行参数例如是否指定了要列出的文件或目录。最简单的版本可以只处理一个文件参数。元数据获取对目标路径调用lstat()函数获取其struct stat信息。如果失败需要像ls一样给出清晰的错误信息例如 “No such file or directory”。信息转换与格式化这是最核心、最繁琐的一步。需要将stat结构体中的数字和位掩码转换成人类可读的字符串。文件类型与权限解析st_mode字段。用户与组名st_uid和st_gid是数字ID需要通过getpwuid()和getgrgid()函数转换为用户名和组名。时间格式化st_mtime是自Epoch1970-01-01 UTC以来的秒数需要使用localtime()和strftime()函数转换为本地时间字符串并实现“半年规则”的格式判断。排版输出按照ls -l的固定列宽和格式将转换好的各字段组合成一行输出。这里需要注意对齐例如链接数、文件大小通常右对齐。3. 核心细节解析与关键函数剖析3.1 解密struct stat信息的宝库struct stat定义在sys/stat.h中它是我们所有数据的来源。其中与我们项目最相关的成员如下struct stat { dev_t st_dev; /* 文件所在设备的ID */ ino_t st_ino; /* Inode号 */ mode_t st_mode; /* 文件类型和权限模式 */ nlink_t st_nlink; /* 硬链接数 */ uid_t st_uid; /* 所有者的用户ID */ gid_t st_gid; /* 所属组的组ID */ dev_t st_rdev; /* 设备ID如果是特殊文件 */ off_t st_size; /* 文件大小字节为单位 */ blksize_t st_blksize; /* 文件系统I/O的块大小 */ blkcnt_t st_blocks; /* 分配的512B块数量 */ time_t st_atime; /* 最后访问时间 */ time_t st_mtime; /* 最后修改时间 */ time_t st_ctime; /* 最后状态变更时间 */ };重点字段解读st_mode这是一个mode_t类型的位掩码bitmask。它的高位bit表示文件类型低位表示文件权限。系统提供了一系列宏来帮助我们检查这些位例如S_ISREG()判断是否是普通文件S_IRUSR表示所有者读权限。st_uid/st_gid这是数字ID。Linux系统中用户和组名只是为了人类方便内核实际识别的是这些数字。我们需要进行“反向查找”。st_mtimetime_t类型通常是一个长整型表示秒数。直接打印这个数字对人类毫无意义。3.2 从数字ID到名称getpwuid和getgrgidstat结构只给了我们用户IDUID和组IDGID。要得到像 “alice” 和 “developers” 这样的名字我们需要查询系统的用户和组数据库。这通过以下两个函数实现struct passwd *getpwuid(uid_t uid);根据UID返回一个passwd结构体指针其中pw_name字段就是用户名。struct group *getgrgid(gid_t gid);根据GID返回一个group结构体指针其中gr_name字段就是组名。这里有一个非常重要的注意事项这两个函数返回的是指向静态内存的指针这意味着后续调用可能会覆盖之前的内容。如果你需要保存用户名或组名必须立即将字符串如pw_name复制到你自己的缓冲区中例如使用strdup()或strcpy。3.3 时间魔法localtime与strftimest_mtime是一个time_t通常为long int。我们需要将其转换为struct tm结构体这个结构体包含了年、月、日、时、分、秒等分解后的时间组件。localtime()函数就是干这个的struct tm *localtime(const time_t *timep);得到struct tm后再使用strftime()函数按照自定义的格式将其格式化成字符串。ls -l使用了两种格式近期文件6个月内%b %e %H:%M例如Jun 15 10:30远期文件%b %e %Y例如Jun 15 2023判断“近期”还是“远期”的逻辑是获取当前时间time(NULL)也转换为struct tm然后比较年份和月份。如果文件年份与当前年份不同或者同年但月份差超过6个月则视为远期文件。3.4 权限位解析位运算的经典应用st_mode字段的解析是位运算的完美教学案例。权限部分由9个位组成分为三组位 8-6: 所有者权限 (USR)位 5-3: 组权限 (GRP)位 2-0: 其他用户权限 (OTH)每一组内的三个位分别代表位 2: 读权限 (R) - 掩码S_IRUSR,S_IRGRP,S_IROTH位 1: 写权限 (W) - 掩码S_IWUSR,S_IWGRP,S_IWOTH位 0: 执行权限 (X) - 掩码S_IXUSR,S_IXGRP,S_IXOTH我们的任务就是检查这些位是否被设置然后相应地输出r、w、x或者-。此外还有三个特殊权限位Set-User-ID (SUID): 当出现在所有者执行位时表现为s或S如果所有者没有执行权限。Set-Group-ID (SGID): 当出现在组执行位时表现为s或S。Sticky Bit: 当出现在其他用户执行位时通常用于目录如/tmp表现为t或T。4. 分步实现与代码剖析4.1 第一步搭建程序框架与参数处理我们先从一个最简单的框架开始处理单个文件参数。#include stdio.h #include stdlib.h #include sys/stat.h #include sys/types.h #include pwd.h #include grp.h #include time.h #include unistd.h #include string.h #include errno.h void print_long_format(const char *filename); int main(int argc, char *argv[]) { if (argc ! 2) { fprintf(stderr, Usage: %s filename\n, argv[0]); exit(EXIT_FAILURE); } print_long_format(argv[1]); return 0; }这个框架很简单它检查是否提供了一个参数然后调用核心函数print_long_format。4.2 第二步实现核心的print_long_format函数这是整个程序的心脏。我们一步步构建它。void print_long_format(const char *filename) { struct stat file_stat; // 1. 使用 lstat 获取文件元数据 if (lstat(filename, file_stat) -1) { perror(lstat); return; } // 2. 解析文件类型和权限 char type_perms[11] ----------; // 10个字符终止符 // 文件类型 if (S_ISREG(file_stat.st_mode)) type_perms[0] -; else if (S_ISDIR(file_stat.st_mode)) type_perms[0] d; else if (S_ISLNK(file_stat.st_mode)) type_perms[0] l; else if (S_ISCHR(file_stat.st_mode)) type_perms[0] c; else if (S_ISBLK(file_stat.st_mode)) type_perms[0] b; else if (S_ISFIFO(file_stat.st_mode)) type_perms[0] p; else if (S_ISSOCK(file_stat.st_mode)) type_perms[0] s; else type_perms[0] ?; // 所有者权限 type_perms[1] (file_stat.st_mode S_IRUSR) ? r : -; type_perms[2] (file_stat.st_mode S_IWUSR) ? w : -; type_perms[3] (file_stat.st_mode S_IXUSR) ? x : -; // 处理SUID if (file_stat.st_mode S_ISUID) { type_perms[3] (type_perms[3] x) ? s : S; } // 组权限 type_perms[4] (file_stat.st_mode S_IRGRP) ? r : -; type_perms[5] (file_stat.st_mode S_IWGRP) ? w : -; type_perms[6] (file_stat.st_mode S_IXGRP) ? x : -; // 处理SGID if (file_stat.st_mode S_ISGID) { type_perms[6] (type_perms[6] x) ? s : S; } // 其他用户权限 type_perms[7] (file_stat.st_mode S_IROTH) ? r : -; type_perms[8] (file_stat.st_mode S_IWOTH) ? w : -; type_perms[9] (file_stat.st_mode S_IXOTH) ? x : -; // 处理Sticky Bit if (file_stat.st_mode S_ISVTX) { type_perms[9] (type_perms[9] x) ? t : T; } type_perms[10] \0; // 确保字符串结束 // 3. 获取用户名和组名 struct passwd *pw getpwuid(file_stat.st_uid); struct group *gr getgrgid(file_stat.st_gid); char *user_name pw ? pw-pw_name : UNKNOWN; char *group_name gr ? gr-gr_name : UNKNOWN; // 4. 格式化时间 char time_buf[80]; struct tm *tm_info localtime(file_stat.st_mtime); time_t now time(NULL); struct tm *now_tm localtime(now); char format[20]; // 判断是否为“近期”文件同年且月份差小于6个月 if ((tm_info-tm_year now_tm-tm_year) (abs(tm_info-tm_mon - now_tm-tm_mon) 6)) { strcpy(format, %b %e %H:%M); } else { strcpy(format, %b %e %Y); } strftime(time_buf, sizeof(time_buf), format, tm_info); // 5. 格式化输出 printf(%s %2lu %-8s %-8s %8lld %s %s\n, type_perms, (unsigned long)file_stat.st_nlink, user_name, group_name, (long long)file_stat.st_size, time_buf, filename); }代码关键点解析错误处理lstat失败时使用perror打印错误这比ls的默认输出更详细但原理相同。类型判断使用S_IS*()系列宏是判断文件类型的标准且可移植的方法。权限位检查使用按位与操作来检查特定的权限位是否被设置。特殊权限处理SUID、SGID、Sticky Bit 的处理逻辑是先检查普通执行位x再叠加特殊权限位根据x是否存在决定显示小写s/t还是大写S/T。用户/组名获取始终检查getpwuid和getgrgid的返回值是否为NULL。在容器或某些特殊环境下ID可能不存在于本地数据库中此时回退到打印数字ID或“UNKNOWN”是更健壮的做法。时间格式化逻辑strftime的%e格式说明符会在单数日期前加空格这与ls -l的行为一致。我们手动实现了“半年规则”的判断逻辑。格式化输出printf中的格式字符串%-8s表示左对齐且宽度为8的字符串%8lld表示右对齐且宽度为8的长长整型。这些宽度值可能需要根据实际用户名、组名的长度进行调整才能完美对齐。真正的ls命令会先遍历所有文件计算各列的最大宽度然后进行动态对齐这是我们简化版与完整版的一个主要区别。4.3 第三步扩展功能——处理目录和多个文件一个实用的ls模拟器应该能处理目录列出目录内所有文件和多个文件参数。这涉及到opendir、readdir、closedir等目录流操作函数。基本思路是在main函数中遍历所有命令行参数。对每个参数调用lstat如果它是目录则打开目录并遍历其中的每个条目跳过.和..为每个条目调用print_long_format如果它不是目录则直接为其调用print_long_format。这会使代码复杂度上升一个数量级因为你需要管理内存、排序条目ls默认按字母顺序排序、以及计算列宽以实现整齐的对齐。5. 常见问题、调试技巧与进阶思考5.1 编译与链接确保在编译时链接必要的库。虽然我们使用的函数大部分在标准C库和POSIX库中但显式指定总是好的。gcc -o my_ls my_ls.c -Wall -Wextra-Wall -Wextra标志能帮你发现很多潜在的代码问题。5.2 调试与问题排查权限位显示错误最常见的原因是位运算逻辑错误。可以打印出st_mode的十六进制值printf(“%o”, file_stat.st_mode)然后手动计算应有的权限与程序输出对比。Linux的stat命令stat filename可以给出权威参考。时间显示不对检查localtime()是否调用成功strftime的格式字符串是否正确。确保你比较的是struct tm的tm_year和tm_mon字段注意tm_year是自1900年起的年数tm_mon是0-11。用户名/组名显示为数字或UNKNOWN这通常发生在文件属于一个当前系统不存在的用户或组比如从另一个系统拷贝过来的文件或Docker容器中的文件。你的程序处理了NULL情况这是正确的。你可以选择打印数字ID%u,%u作为备选方案。符号链接处理记住我们用的是lstat所以对于符号链接st_size字段是链接路径字符串的长度而不是目标文件的大小。如果你想要模拟ls -lL就需要对符号链接使用stat()。5.3 与真实ls -l的差异与进阶挑战我们的简化版本已经实现了核心功能但与GNU coreutils中的ls相比还缺少很多优化和特性列对齐真正的ls会先收集所有要显示条目的全部信息计算出“链接数”、“用户名”、“组名”、“文件大小”这几列各自需要的最大宽度然后进行动态的右对齐或左对齐。我们的版本使用了固定宽度如%-8s当名字很长时会对不齐。排序ls默认按文件名字母顺序排序。实现排序需要将目录条目读入一个数组然后用qsort进行排序。隐藏文件ls默认不显示以.开头的文件需要-a选项。我们的目录遍历版本需要添加这个过滤逻辑。颜色输出ls --colorauto会根据文件类型可执行文件、目录、符号链接等显示不同颜色。这涉及到终端转义序列ANSI escape codes和更复杂的文件类型/权限判断。块大小格式化ls -lh会用K、M、G等单位显示文件大小。这需要实现一个将字节数转换为人类可读格式的函数。性能对于包含成千上万文件的目录先统计再输出的方式两次遍历比我们的流式输出更耗时但能保证对齐。这是一个典型的空间换时间的权衡。实现这些特性中的任何一个都能让你对Linux编程和ls命令的理解更深一层。例如实现动态列对齐会让你熟悉链表或动态数组的内存管理实现颜色输出会让你了解终端是如何工作的实现-h选项则是一个简单的算法练习。通过这个从零模拟ls -l的项目你穿透了命令行工具的表层直接触摸到了Linux文件系统API的基石。你不再只是stat函数的使用者而是成为了其行为的解读者。下次当你再键入ls -l你看到的将不再是一行行冰冷的文本而是一幅由inode编号、权限位掩码、时间戳和用户ID共同构成的、动态的系统画卷。这种从“知其然”到“知其所以然”的转变正是系统编程魅力所在。你可以尝试在此基础上挑战实现-a、-t按时间排序、-r反向排序甚至-lh选项每一步都会让你对Linux环境的掌控力更上一层楼。

相关新闻

Tokenmaxxing应对:LLM应用预算控制与工程实践

Tokenmaxxing应对:LLM应用预算控制与工程实践

最近在开发群里又聊到一个让不少团队头疼的话题:Tokenmaxxing。很多人一开始觉得这个词很酷,结果一句话没聊完,预算爆了、接口被封、账单翻倍。更现实的一种情况是,云平台侧开始对这类高消耗的调用方式亮出红线,典型的…

2026/8/29 20:04:22 阅读更多 →
强化学习驱动持久图空间随机动力学:方法与实践

强化学习驱动持久图空间随机动力学:方法与实践

这个课题从标题看就很有特点:它把拓扑数据分析(TDA)中的持久图(Persistence Diagram)、随机动力学(Stochastic Dynamics)和强化学习(Reinforcement Learning)三个看似不相…

2026/8/29 20:03:39 阅读更多 →
一个 agent 指挥一群 agent

一个 agent 指挥一群 agent

一个画面:它不写代码,它派活 设想你让 Hermes 实现一个功能。它当然可以自己上手,调 terminal、写文件、跑测试。但 v0.16.0 里它多了一个选择:把这单活外包出去。 在 skills/autonomous-ai-agents/ 这个目录下,源码里…

2026/8/28 18:03:59 阅读更多 →

最新新闻

Partmode开源CAD:浏览器里的SolidWorks替代方案体验与部署评估

Partmode开源CAD:浏览器里的SolidWorks替代方案体验与部署评估

Partmode 这个开源项目,最近引起我注意的倒不是“开源 CAD”这个概念本身,而是它的 Live browser demo——不需要安装庞大的桌面客户端,打开浏览器就能实际体验建模流程。定位上,它被看作 SolidWorks 的开源替代思路,对…

2026/8/29 20:04:25 阅读更多 →
最小生成树算法实战:Kruskal与Prim原理、实现与应用场景解析

最小生成树算法实战:Kruskal与Prim原理、实现与应用场景解析

1. 项目概述:从实际问题到最小生成树在解决现实中的网络连接问题时,我们常常会遇到一个经典场景:如何用最低的成本,将一组分散的点(比如城市、基站、服务器节点)全部连接起来,并且保证整个网络是…

2026/8/29 20:04:25 阅读更多 →
最大流算法详解:从Edmonds-Karp到最小割定理的实战指南

最大流算法详解:从Edmonds-Karp到最小割定理的实战指南

1. 项目概述:从水管网络到信息高速公路 想象一下,你所在的城市有一个庞大的自来水供水网络。水源地是几个大型水库,而千家万户则是用水终端。连接水库和用户之间的,是粗细不一、错综复杂的输水管道,每条管道在单位时间…

2026/8/29 20:04:25 阅读更多 →
最小生成树算法详解:Kruskal与Prim的核心思想、代码实现与选型指南

最小生成树算法详解:Kruskal与Prim的核心思想、代码实现与选型指南

1. 从实际问题到图论模型:为什么我们需要最小生成树?如果你做过一些关于资源分配、网络铺设或者路径规划的方案,大概率会遇到一个经典问题:如何用最低的成本,把一堆分散的点连接成一个连通的整体,并且保证任…

2026/8/29 20:04:25 阅读更多 →
每日资讯快报:Cursor 被 SpaceX 收购,OpenAI 直接断供模型~

每日资讯快报:Cursor 被 SpaceX 收购,OpenAI 直接断供模型~

今天 AI 圈最炸的只有一条:Cursor 被 SpaceX 收购,OpenAI 直接断供模型。往下还有 GitHub AI 热榜和 DeepSeek harness 插件生态的新动静,三分钟扫完。 【今日 AI 快报】 Cursor 被收购,OpenAI 断供模型:SpaceX 以 60…

2026/8/29 20:04:25 阅读更多 →
【和豆包一起工作】无限余额钱包应用

【和豆包一起工作】无限余额钱包应用

这是和豆包一起工作,开发的一个钱包应用,哪位同事或者朋友帮我验证一下收款里面的付款二维码的功能是否已经实现。 无限钱包 用户: 添加二维码给支付宝,微信付款功能 豆包: 我识别到用户的核心诉求是为支付宝和微信付款功能添加二维码&#…

2026/8/29 20:03:24 阅读更多 →

日新闻

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

一、设置环境变量etc目录下的profile.d文件目录 /etc/profile.d1、编写 vi test.sh文件内容# jdk变量 export ZHK_HOME/root export PATH$PATH:$ZHK_HOME/test # 可以取出来ZHK_HOME变量给ZZZ_HOME赋值 export ZZZ_HOME${ZHK_HOME}/test2、刷新 执行source /etc/profile 命令使…

2026/8/29 0:00:24 阅读更多 →
【JavaScript】内存管理-垃圾回收机制-内存泄露

【JavaScript】内存管理-垃圾回收机制-内存泄露

内存管理 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()和free()。 而 JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。 整…

2026/8/29 0:00:24 阅读更多 →
Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP 的目标是把 MCP(Model Context Protocol)能力延伸到真实嵌入式硬件实验室:AI Agent 通过一个标准化的 MCP Server,就能查看目标板状态、控制上电断电、复位开发板、读取串口日志,甚至执行镜像刷写。对于经…

2026/8/29 0:00:24 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/29 18:08:35 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/28 23:05:07 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/28 19:47:53 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/29 4:34:53 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/28 17:43:04 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/29 2:05:18 阅读更多 →