PC上浏览器是如何查询DNS 缓存的呢?

news2024/11/16 11:13:05

通过 ipconfig /displaydns 的显示结果可以获取本机的 DNS 缓存信息,那么浏览器是如何获取本机的 DNS 缓存。

答案是:浏览器获取本机的 DNS 缓存主要是通过操作系统提供的接口来获取,。

具体的获取途径如下:

  1. 先查询自身缓存:浏览器会首先检查自己内部维护的 DNS 缓存。当用户访问一个网站时,浏览器会将域名对应的 IP 地址缓存下来,以便下次访问时快速获取。不同的浏览器对 DNS 缓存的存储时间和策略可能会有所不同,但一般来说,浏览器会在一定时间内保留 DNS 缓存以提高访问速度。例如,谷歌浏览器的 DNS 缓存时间相对较短。
  2. 若浏览器缓存未命中,查询操作系统缓存:如果浏览器自身的缓存中没有找到对应的 DNS 记录,它会向操作系统发出请求,获取操作系统级别的 DNS 缓存。操作系统会维护一个 DNS 缓存,其中存储了最近访问过的域名及其对应的 IP 地址。在 Windows 系统中,可以使用 ipconfig /displaydns 命令查看操作系统的 DNS 缓存,但这只是一种查看方式,浏览器是通过操作系统提供的相关系统调用接口来获取这些缓存信息的。
  3. 读取本地 hosts 文件(若操作系统缓存未命中):如果操作系统的 DNS 缓存中也没有找到所需的 DNS 记录,浏览器会检查本地的 hosts 文件。hosts 文件是一个本地的文本文件,可以手动添加域名和 IP 地址的映射关系。浏览器会按照 hosts 文件中的配置来解析域名,如果找到对应的映射关系,就会使用文件中指定的 IP 地址。
  4. 向 DNS 服务器发起请求(若前面途径都未获取到):如果在前面的步骤中都没有找到对应的 DNS 记录,浏览器会向配置的 DNS 服务器发起请求,获取域名对应的 IP 地址。DNS 服务器会根据域名的层级结构,从根域名服务器开始递归查询,直到找到负责该域名的权威域名服务器。

浏览器获取本机的 DNS 缓存主要是通过操作系统提供的以下几种常见接口来获取:

  1. 系统调用接口:操作系统会提供一系列的系统调用函数,浏览器通过调用这些函数来访问操作系统级别的 DNS 缓存。不同的操作系统有不同的系统调用方式,但通常都是在底层实现了对 DNS 缓存信息的读取操作。例如,在 Windows 系统中,应用程序可以通过相关的系统 API 来获取 DNS 缓存中的记录;在 Linux 系统中,也有对应的系统调用接口可供程序使用。这些接口允许浏览器向操作系统请求特定域名的 IP 地址解析结果,如果在操作系统的 DNS 缓存中有该记录,操作系统会将其返回给浏览器2。
  2. 网络库接口:操作系统通常会提供一些网络相关的库,这些库封装了底层的网络操作,包括对 DNS 缓存的访问。浏览器可以使用这些网络库提供的接口来获取 DNS 缓存信息。例如,在一些操作系统中,网络库会提供函数或方法,让浏览器能够查询特定域名的缓存解析结果。这样,浏览器不需要直接与操作系统的底层系统调用打交道,而是通过相对简单的网络库接口来获取所需的 DNS 缓存数据。

以下分别以几种常见的编程语言结合不同操作系统的常用 API 为例,介绍如何编程实现利用操作系统的 API 获取 DNS 缓存:

Windows 系统(使用 C 语言结合 DnsQuery API)

#include <windows.h>
#include <windns.h>

int main() {
    DNS_STATUS status;
    PDNS_RECORD pDnsRecord;
    // 要查询的域名,这里以示例域名为例,实际可替换为其他域名
    PCSTR domainName = "www.example.com"; 
    
    // 调用DnsQuery API进行查询,尝试获取DNS缓存或发起新查询
    status = DnsQuery(domainName, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsRecord, NULL);
    if (status == ERROR_SUCCESS) {
        // 如果查询成功,遍历并输出DNS记录信息
        PDNS_RECORD currentRecord = pDnsRecord;
        while (currentRecord!= NULL) {
            // 输出IP地址等相关信息,这里简单示意,可根据实际细化处理
            printf("IP Address: %s\n", currentRecord->Data.A.IpAddress.String);
            currentRecord = currentRecord->pNext;
        }
        DnsRecordListFree(pDnsRecord, DnsFreeRecordListDeep);
    } else {
        // 如果查询失败,输出错误信息
        printf("DnsQuery failed with error code: %d\n", status);
    }
    return 0;
}

在上述代码中:

  1. 首先引入了必要的头文件 <windows.h> 和 <windns.h>,它们包含了在 Windows 环境下进行 DNS 查询相关操作所需的函数声明、结构体定义等内容。
  2. 在 main 函数里,定义了变量用于存储 DNS 查询的状态以及查询结果的记录指针等。
  3. 通过 DnsQuery 函数传入要查询的域名(示例中为 "www.example.com" )、记录类型(这里选择 DNS_TYPE_A 表示查询 IPv4 地址对应的记录)以及其他相关查询参数,尝试从本地 DNS 缓存获取记录,如果缓存没有则可能向外部 DNS 服务器发起查询。
  4. 根据查询结果进行不同处理,如果查询成功就遍历并输出获取到的 IP 地址等相关 DNS 记录信息,若失败则输出相应的错误代码提示信息。

Linux 系统(使用 C 语言结合 getaddrinfo API)

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main() {
    struct addrinfo hints, *result, *rp;
    int s;
    // 要查询的域名,可按需替换
    const char *domain = "www.example.com"; 
    
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;  // 支持IPv4和IPv6
    hints.ai_socktype = SOCK_STREAM;  // TCP类型的套接字

    // 调用getaddrinfo API进行查询,先查看本地DNS缓存
    s = getaddrinfo(domain, NULL, &hints, &result);
    if (s!= 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        return 1;
    }

    // 遍历查询结果并输出相关IP地址信息
    for (rp = result; rp!= NULL; rp = rp->ai_next) {
        void *addr;
        char *ipver;
        if (rp->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)rp->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)rp->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }
        char ipstr[INET6_ADDRSTRLEN];
        inet_ntop(rp->ai_family, addr, ipstr, sizeof(ipstr));
        printf("IP Address (%s): %s\n", ipver, ipstr);
    }

    freeaddrinfo(result);
    return 0;
}

  1. 包含了多个必要的头文件,如 <stdio.h> 用于标准输入输出操作、<stdlib.h> 用于内存管理相关操作、<netdb.h> 和 <arpa/inet.h> 用于网络地址相关的处理以及 DNS 查询功能实现。
  2. 在 main 函数中,先对 hints 结构体进行初始化,设置了地址族(支持 IPv4 和 IPv6)以及套接字类型等参数,然后调用 getaddrinfo 函数传入要查询的域名、相关参数提示信息以及用于存储结果的指针变量,该函数会先查看本地 DNS 缓存获取记录,若没有再按流程向外部 DNS 服务器查询。
  3. 根据 getaddrinfo 的返回结果进行处理,如果成功就遍历返回的地址信息列表,判断是 IPv4 还是 IPv6 地址并进行相应的格式转换后输出,若失败则输出对应的错误提示信息,最后释放申请的内存资源。

macOS 系统(使用 Objective-C 语言结合 CFHostCreateWithName API)

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *domain = @"www.example.com";
        CFStringRef domainCF = (__bridge CFStringRef)domain;
        // 使用CFHostCreateWithName API创建主机对象,过程中会检查本地DNS缓存
        CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, domainCF);
        if (host!= NULL) {
            // 尝试获取主机的IP地址信息
            if (CFHostStartInfoResolution(host, kCFHostAddresses, NULL) == kCFHostStartInfoResolutionSuccess) {
                CFArrayRef addresses = CFHostGetAddressing(host, NULL);
                if (addresses!= NULL) {
                    CFIndex count = CFArrayGetCount(addresses);
                    for (CFIndex i = 0; i < count; i++) {
                        struct sockaddr_storage *addr = (struct sockaddr_storage *)CFArrayGetValueAtIndex(addresses, i);
                        char ipstr[INET6_ADDRSTRLEN];
                        if (addr->ss_family == AF_INET) {
                            struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr;
                            inet_ntop(AF_INET, &(ipv4->sin_addr), ipstr, sizeof(ipstr));
                            NSLog(@"IP Address (IPv4): %s", ipstr);
                        } else if (addr->ss_family == AF_INET6) {
                            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr;
                            inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipstr, sizeof(ipstr));
                            NSLog(@"IP Address (IPv6): %s", ipstr);
                        }
                    }
                }
            }
            CFRelease(host);
        }
    }
    return 0;
}

在这段 Objective-C 代码中:

  1. 首先引入了 <Foundation/Foundation.h> 头文件,它提供了在 macOS 系统下进行基础开发的诸多类和函数等。
  2. 在 main 函数里,定义了要查询的域名字符串,并通过类型转换将其转换为 CFStringRef 类型,因为 CFHostCreateWithName 函数需要该类型的参数。
  3. 使用 CFHostCreateWithName 函数创建一个主机对象,在这个过程中,系统会先查看本地 DNS 缓存来获取对应的 IP 地址解析记录。如果创建成功,接着尝试启动信息解析获取主机的 IP 地址信息,若解析成功,获取到地址数组后,遍历该数组,根据地址的类型(IPv4 或 IPv6)进行相应的格式转换并输出 IP 地址信息,最后释放创建的主机对象占用的资源。

需要注意的是,以上代码示例只是简单演示如何利用对应操作系统的相关 API 获取 DNS 缓存相关信息,实际应用中可能需要根据具体需求进一步完善功能、添加错误处理以及适配更多复杂场景等。

参考内容:

浏览器获取本机的 DNS 缓存有多种途径。首先,可以通过开发者工具查看谷歌浏览器的 DNS 缓存,按下 F12 键打开开发者工具,切换到 “Application” 选项卡,在左侧导航栏的 “Storage” 选项中可查看相应缓存数据。此外,在 Windows 操作系统中,谷歌浏览器的缓存文件路径通常为 C:\Users\{用户名}\AppData\Local\Google\Chrome\User Data\Default\Cache,但直接打开该文件夹看到的是二进制文件,需借助特定工具才能查看具体内容。火狐浏览器可在地址栏中输入 about:cache,点击 disk→list cache entries 查看缓存信息。微软 Edge 浏览器输入 edge://net-internals/#dns 可查看与 DNS 相关的缓存信息,但此功能可能需要手动开启记录到本地磁盘才能正常查看具体内容,也可通过开发者工具查看缓存。

关于本机的 DNS 缓存获取,在 Windows 系统中可以使用 cmd 命令 ipconfig /displaydns 查看操作系统的 DNS 缓存。浏览器也会按照一定的频率缓存 DNS 记录,例如 chrome://net-internals/#dns 可以查看 Chrome 浏览器的 DNS 缓存。浏览器获取本机 DNS 缓存的途径并非单一,不同浏览器有不同的查看方式,同时也可以通过系统命令来查看操作系统层面的 DNS 缓存。

综上所述,浏览器获取本机 DNS 缓存可以通过自身的特定方式以及系统命令等多种途径来实现。

谷歌浏览器获取本机 DNS 缓存途径

在谷歌浏览器中,可以通过在地址栏输入 “chrome://net-internals/#dns” 来查看本机的 DNS 缓存。访问该页面后,会显示当前所有 DNS 缓存,通过点击 “Clear host cache”,可以清空所有 DNS 缓存。有时候此方法可能不能立刻生效,可以使用另外一个设置,在地址栏中输入 “chrome://settings/” 并回车,通过搜索 “预测网络操作” 找到配置项 “预测网络操作,以提高网页加载速度”,去掉前面的勾即可。此外,谷歌浏览器对每个域名会默认缓存 60s,但现在需要手动开启记录到本地磁盘才能正常查看具体内容。例如,当在谷歌浏览器的 url 地址栏输入 “chrome://net-internals/#dns” 后,页面会显示诸如 “Resolved lP addresses of ‘www.baidu.com’:(‘112.80.248.75’, ‘112.80.248.76’).No data on which protocols are supported.Host resolver cache” 的信息,这里的 “Host resolver cache” 就是主机解析器缓存,可以点击 “Clear host cache” 清除缓存记录。

火狐浏览器获取本机 DNS 缓存途径

在火狐浏览器中,可以在地址栏中输入 “about:config” 并回车,可能会出现一个警告信息,直接点击按钮进入,会出现火狐的所有配置信息。通过搜索 “dns” 进行过滤,可以看到一项名为 “network.dnsCacheExpirationGracePeriod” 项,它对应的值就是 DNS 缓存的时间,双击此项,会出现修改的提示框,填入 0(不缓存 DNS)即可。Firefox 有 dns 缓存功能,但是默认缓存时间只有 1 分钟,可以通过修改该默认值加快 DNS 解析速度,方法如下:打开一个新的窗口,地址栏输入 “about:config”,回车,进入设置界面。然后搜索 “network.dnsCacheExpiration”,把原来的 60 改成 6000(表示缓存 6000 秒),再搜索 “network.dnsCacheEntries” 把默认的 20 改成 1000(表示缓存 1000 条)。如果没有上面两个项目,可以在地址栏中输入 “about:cache” 并回车,点击 “disk(磁盘)→list cache entries(缓存条目列表)”,即可看到火狐浏览器的缓存信息,包括缓存文件的大小、类型、存储路径等。

微软 Edge 浏览器获取本机 DNS 缓存途径

在微软 Edge 浏览器中,可以输入 “edge://net-internals/#dns” 可查看与 DNS 相关的缓存信息,但此功能可能需要手动开启记录到本地磁盘才能正常查看具体内容。类似于谷歌浏览器,也可以通过开发者工具查看缓存。按下 F12 打开开发者工具,切换到 “Application” 选项卡,在 “Storage” 下查看 “Cookies”“Local Storage”“Session Storage” 等缓存数据。

Windows 系统通过 cmd 命令获取 DNS 缓存

在 Windows 系统中,可以通过 cmd 命令来获取和操作 DNS 缓存。首先按下快捷键 “win+r” 调出运行窗口,在窗口处输入 “cmd”。打开 “命令提示符” 窗口后,在窗口处输入命令 “ipconfig /displaydns” 来进行查看系统内的 DNS 缓存。如果要清空 DNS 缓存,可以执行命令 “ipconfig /flushdns” 命令。再次输入命令 “ipconfig /displaydns” 来确认是否清空了 DNS 缓存。成功后,系统将返回相应消息,如 “Windows IP Configuration Successfully flushed the DNS Resolver Cache.”。

浏览器获取本机 DNS 缓存的原理

浏览器获取本机 DNS 缓存是为了提高网页加载速度。不同的浏览器有不同的缓存机制和获取途径。一般来说,浏览器会优先检查自身的缓存,如果未命中则会进一步查询操作系统的缓存、hosts 文件等。例如,谷歌浏览器会先查询自身的 DNS 缓存,若未找到则会继续查询操作系统缓存等。火狐浏览器通过特定的配置项和命令来查看和操作 DNS 缓存。微软 Edge 浏览器则可以通过特定的地址和开发者工具来查看相关缓存信息。而 Windows 系统通过 cmd 命令可以直接查看和清空系统内的 DNS 缓存。这些方法都是为了提高网络访问的效率,减少 DNS 查询的时间,从而提升用户的上网体验。

浏览器获取本机 DNS 缓存的途径多种多样,不同的浏览器和操作系统提供了不同的方法。用户可以根据自己的需求和使用习惯选择合适的方式来查看和管理 DNS 缓存。无论是谷歌浏览器、火狐浏览器还是微软 Edge 浏览器,都在不断优化自身的缓存机制,以提供更快速、高效的网络访问体验。同时,Windows 系统的 cmd 命令也为用户提供了一种直接管理 DNS 缓存的方式,方便用户在需要时进行操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2241465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日OJ题_牛客_DP36 abb_C++_Java

目录 牛客_DP36 abb 题目解析 C代码1暴力 C代码2DP Java代码 牛客_DP36 abb abb_牛客题霸_牛客网 描述&#xff1a; leafee 最近爱上了 abb 型语句&#xff0c;比如“叠词词”、“恶心心” leafee 拿到了一个只含有小写字母的字符串&#xff0c;她想知道有多少个 &quo…

Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)

目录 一、String字符串类型介绍 二、常见命令 1、SET 2、GET 3、MGET 4、MSET 使用MGET 和 使用多次GET的区别 5、DEL 6、SETNX SET、SET NX和SET XX执行流程 7、INCR 8、INCRBY 9、DECR 10、DECYBY 11、INCRBYFLOAT 12、APPEND 13、GETRANGE 14、SETRANGE …

Dubbo 3.x源码(25)—Dubbo服务引用源码(8)notify订阅服务通知更新

基于Dubbo 3.1&#xff0c;详细介绍了Dubbo服务的发布与引用的源码。 此前我们学习了接口级的服务引入订阅的refreshInterfaceInvoker方法&#xff0c;当时还有最为关键的notify服务通知更新的部分源码没有学习&#xff0c;本次我们来学习notify通知本地服务更新的源码。 Dubb…

STM32+AI语音识别智能家居系统

基于 STM32 和 AI 语音识别的智能家居系统的详细硬件和软件设计&#xff0c;包括各个模块的详细描述和代码示例。 一、硬件设计 1. 微控制器&#xff08;STM32&#xff09;&#xff1a; 选择 STM32F7 系列或更高性能的芯片&#xff0c;如 STM32F767ZIT6&#xff0c;以满足处理…

飞凌嵌入式RK3576核心板已适配Android 14系统

在今年3月举办的RKDC2024大会上&#xff0c;飞凌嵌入式FET3576-C核心板作为瑞芯微RK3576处理器的行业首秀方案重磅亮相&#xff0c;并于今年6月率先量产发货&#xff0c;为客户持续稳定地供应&#xff0c;得到了众多合作伙伴的认可。 FET3576-C核心板此前已提供了Linux 6.1.57…

elementUI input 禁止内容两端存在空格,或者是自动去除两端空格

需求 项目中有需求&#xff1a;输入框中禁止内容两端存在空格&#xff0c;或者是自动去除两端空格。 解决方法 vue的api文档中有过介绍&#xff0c;使用.trim可以去掉用户输入内容中两端的空格&#xff0c;如下图 代码 <el-input v-model.trim"name" cleara…

初识算法 · 位运算(end)

目录 前言&#xff1a; 题目解析 算法原理 算法编写 前言&#xff1a; 本文作为初识算法 位运算的最后一篇文章&#xff0c;使用一道hard题目来结束这个专题&#xff0c;题目的链接为&#xff1a; 面试题 17.19. 消失的两个数字 - 力扣&#xff08;LeetCode&#xff09;…

3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)

3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用) 文章目录 3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)前言1. Spring Cloud Eureka 的概述1.1 服务治理概述1.2 服务注册与发现 2. 实践&#xff1a;创建单机 Eureka Server 注册中心2.1 需求说明 图解…

springboot实现简单的数据查询接口(无实体类)

目录 前言&#xff1a;springboot整体架构 1、ZjGxbMapper.xml 2、ZjGxbMapper.java 3、ZjGxbService.java 4、ZjGxbController.java 5、调用接口测试数据是否正确 6、打包放到服务器即可 前言&#xff1a;springboot整体架构 文件架构&#xff0c;主要编写框选的这几类…

awk(常用)

这个有点难 O.o 一、awk # 语法 awk 参数 模式 {动作} 文件# 第一列&#xff0c;包含p的 $1~"p" # 第一列&#xff0c;不包含p的 $1!~"p" # 开始时干嘛&#xff0c;结束时干嘛 awk BEGIN{开始时做的事}END{结束时做的事}{print $0} 文件 1、内置变量&…

EXPLAIN优化慢SQL

项目中发现数据查询很慢&#xff0c;导致前端超时等待的问题。经过日志打印发现&#xff0c;查询sql耗时10秒以上&#xff0c;相关sql如下&#xff1a; select distincttablemodel.*from pjtask_model tablemodelJOIN buss_type_permission a ON (tablemodel.fields_data_id …

Skywalking搭建-来自于图灵课堂

Skywalking主要用于链路追踪&#xff0c;日志收集查看&#xff0c;异常日志查看&#xff0c;服务监控弱一些&#xff0c;服务器监控可以使用prometheus 一、搭建服务端&#xff0c;使用startup.bat启动 配置持久化&#xff0c;如果是用mysql持久化&#xff0c;拷贝mysql链接包…

ZooKeeper单机、集群模式搭建教程

单点配置 ZooKeeper在启动的时候&#xff0c;默认会读取/conf/zoo.cfg配置文件&#xff0c;该文件缺失会报错。因此&#xff0c;我们需要在将容器/conf/挂载出来&#xff0c;在制定的目录下&#xff0c;添加zoo.cfg文件。 zoo.cfg logback.xml 配置文件的信息可以从二进制包…

计算机网络(11)和流量控制补充

这一篇对数据链路层中的和流量控制进行详细学习 流量控制&#xff08;Flow Control&#xff09;是计算机网络中确保数据流平稳传输的技术&#xff0c;旨在防止数据发送方发送过多数据&#xff0c;导致接收方的缓冲区溢出&#xff0c;进而造成数据丢失或传输失败。流量控制通常…

二元一次不定方程@整数解问题

文章目录 二元一次不定方程|整数解定理1整数解存在充要条件定理2 通解特解知识回顾利用辗转相除法求例 使用表达式凑出通解 二元一次不定方程|整数解 二元一次不定方程的一般形式为 a x b y c ax by c axbyc(1) 其中 a a a、 b b b、 c c c 是整数&#xff0c;且 a a a…

深入理解Flutter生命周期函数之StatefulWidget(一)

目录 前言 1.为什么需要生命周期函数 2.开发过程中常用的生命周期函数 1.initState() 2.didChangeDependencies() 3.build() 4.didUpdateWidget() 5.setState() 6.deactivate() 7.dispose() 3.Flutter生命周期总结 1.调用顺序 2.函数调用时机以及主要作用 4.生…

llama factory lora 微调 qwen2.5 7B Instruct模型

项目背景 甲方提供一台三卡4080显卡 需要进行qwen2.5 7b Instruct模型进行微调。以下为整体设计。 要使用 LLaMA-Factory 对 Qwen2.5 7B Instruct模型 进行 LoRA&#xff08;Low-Rank Adapters&#xff09;微调&#xff0c;流程与之前提到的 Qwen2 7B Instruct 模型类似。LoRA …

机器学习day2-特征工程

四.特征工程 1.概念 一般使用pandas来进行数据清洗和数据处理、使用sklearn来进行特征工程 将任意数据&#xff08;文本或图像等&#xff09;转换为数字特征&#xff0c;对特征进行相关的处理 步骤&#xff1a;1.特征提取&#xff1b;2.无量纲化&#xff08;预处理&#xf…

Llama架构及代码详解

Llama的框架图如图&#xff1a; 源码中含有大量分布式训练相关的代码&#xff0c;读起来比较晦涩难懂&#xff0c;所以我们对llama自顶向下进行了解析及复现&#xff0c;我们对其划分成三层&#xff0c;分别是顶层、中层、和底层&#xff0c;如下&#xff1a; Llama的整体组成…

stm32在linux环境下的开发与调试

环境安装 注&#xff1a;文末提供一键脚本 下载安装stm32cubeclt 下载地址为&#xff1a;https://www.st.com/en/development-tools/stm32cubeclt.html 选择 linux版本下载安装 安装好后默认在家目录st下 > $ ls ~/st/stm32cubeclt_1.16.0 …