[OS] A4-前菜介绍

从你的描述来看,这段话是给你的一些 预备知识mkfs工具的使用 提示,帮助你了解如何构建和管理文件系统,特别是关于 xv6 文件系统的一些基本操作。

我会通过比喻和通俗化的方式逐步解释:


预备知识:xv6 文件系统的基本结构

  1. 文件系统的构建
    文件系统就像一个巨大的 书库,里面存放着你所有的文件(数据块)。在开始实现文件系统的功能之前,你需要了解这个书库是如何构建的。就像你需要了解书架的设计、每一层存放了多少书、怎么存放书籍,文件系统也是在操作这些基本的“块”(blocks)。

  2. mkfs 程序
    mkfs 程序就像是 构建书架 的工具,它根据指定的参数建立一个文件系统(类似创建一个空的书库)。在 mkfs 执行时,它会给你一些信息,比如文件系统有多少个“书架”(数据块)可以使用。

  3. FSSIZE 参数
    FSSIZE 就是设定书库的 大小,它告诉文件系统最多可以有多少个块(书架)。在你给出的例子中,FSSIZE 被设置为 200,000 个块,这意味着整个文件系统最多可以拥有 200,000 个块来存储数据。

  4. 输出信息: 当你运行 mkfs 时,它会输出文件系统的基本信息,告诉你文件系统的构建情况。例如:

    nmeta 70 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 25) blocks
    199930 total 200000
    

    这里的意思是,文件系统的总共有 200,000 个块,其中:

    • 70 个块用于元数据(这些是描述文件系统本身的数据块)
    • 199,930 个块用于实际存储数据(数据块)

    你可以把这看作是文件系统构建后,书架和书箱的分配情况:70 个书架用于存放“书库”的管理信息,其余的都用来存放实际的书籍(数据)。

  5. 重建文件系统
    如果在开发过程中你需要重新构建文件系统(比如修改了文件系统的设计),你可以运行 make clean,这会删除之前的文件系统,强制重新构建一个新的 fs.img


通俗化解释:

  • 你在做这个作业时,可以把 文件系统 想象成一个书库,每本书就是一个数据块。
  • mkfs 就像是一个工具,帮助你搭建这个书库,它决定书库一共会有多少个书架(块)。
  • 在文件系统创建过程中,FSSIZE 就是控制书库的总容量(有多少个书架)。比如,200,000 块表示书库有 200,000 个“书架”,你可以用它们来存放数据。
  • 元数据 是文件系统本身的管理信息,类似书库的管理者放置在特殊书架上的信息,比如如何分类、哪些书架还空着等。
  • 数据块 就是实际存放文件内容的块,也就是你可以用来存放实际“书”的地方。

通过这样的理解,你会更清楚文件系统构建的基本框架,以及如何使用 mkfs 来创建一个文件系统。


格式指南

项目的结构如下图所示。你也可以使用 ls 命令检查你的目录结构是否正确。目录结构不匹配将导致扣分

对于本次作业,你不需要为附加题(Bonus Part)单独创建文件夹。source 文件夹应包含以下四个文件:

  • fs.c
  • file.h
  • fs.h
  • sysfile.c

如果要提交第 4 次作业的附加题实现,请单独提交以下文件:

  • fs_ec.h
  • fs_ec.c

示例目录结构如下:

main@ubuntu:~/Desktop/Assignment_4_120010001$ ls
Report.pdf  source/
(一个文件夹和一个 PDF 文件)

source 文件夹下:

main@ubuntu:~/Desktop/Assignment_4_120010001/source$ ls
file.h  fs.c  fs.h  sysfile.c
(两个 .c 文件和两个 .h 文件)

请将包含所有所需文件的文件夹压缩成一个 zip 文件,文件名格式应为你的学号,具体如下:

示例文件名:Assignment_4_120010001.zip
报告(Report)应以 PDF 格式提交,并与源代码文件一起包含在压缩包中。格式不符将导致扣分

压缩代码的示例步骤:

main@ubuntu:~/Desktop$ zip -q -r Assignment_4_120010001.zip Assignment_4_120010001
main@ubuntu:~/Desktop$ ls
Assignment_4_120010001                 
Assignment_4_120010001.zip

以下是对这段说明的翻译和整理:


指导说明

  1. 限制范围
    你的实现范围仅限于以下四个文件:

    • fs.c
    • file.h
    • fs.h
    • sysfile.c

    代码需要从标记为 "TODO:" 的注释部分开始实现。

  2. 测试程序入口
    测试程序的入口文件是 bigfile.csymlinktest.c,它们位于 xv6-labs-2022/user 目录下。
    (这是你开始了解测试如何运行的地方。)

  3. 带有 (*) 的部分

    • 这些部分是引导性内容,介绍了工具和函数,帮助你理解系统的功能以及这些组件如何协同工作。
    • 这些部分的代码你需要仔细阅读和理解,但不要修改,除非是标记了 "TODO:" 的部分。
    指导建议:
    1. 先理解引导部分的函数是如何工作的,以及如何使用这些函数。
    2. 在开始实现作业之前,确保你已经对相关内容有了基本的理解。
    3. 我们认为这些引导部分的内容已经足够完成本次作业。
  4. 可选内容(兴趣拓展):

    • 如果你对 xv6 系统感兴趣并希望深入学习,欢迎阅读《xv6-book》以获取更多细节:
      xv6-book PDF
  5. 没有 (*) 的部分

    • 这些部分是需要你实现的 "TODO:" 部分,包含逻辑说明。
    • 在这些部分,你需要根据引导部分介绍的逻辑和提供的 API 来实现函数。
  6. 实现提示

    • 示例代码不会提供
    • 你需要根据引导部分提供的逻辑和 API 自行推导和实现代码功能。

预先准备与设计(吐槽:这部分作业比3050的指导清晰多了)

任务 1:支持大文件


1. 当前 xv6 文件系统的文件大小限制

  • 现状
    • 目前 xv6 文件的最大大小是 268 个块,即 268 × BSIZE 字节BSIZE 在 xv6 中是 1024 字节,即一个块的大小)。
    • 这个限制来源于 xv6 的 inode 结构:
      • 每个 inode 包含 12 个直接块指针1 个单重间接块指针
      • 单重间接块指针 指向一个块,该块中可以存储 256 个数据块的地址
      • 计算文件最大块数:12 + 256 = 268

2. 当前测试程序问题:bigfile 命令

  • 测试失败原因
    • bigfile 命令尝试创建一个 尽可能大的文件 并报告其大小。
    • 提供的模板程序无法写满 256 块,因为测试期望文件能够支持 65803 块
    • 原因是:未修改的 xv6 系统将文件限制在 268 块,而不是测试期望的 65803 块。

3. 目标:实现双重间接块

  • 修改需求

    • 修改 xv6 文件系统,使其支持 双重间接块
    • 每个 inode 添加一个 双重间接块指针。具体逻辑:
      1. 双重间接块指针 指向一个块(双重间接块),该块包含 256 个单重间接块的地址
      2. 每个单重间接块包含 256 个数据块的地址
  • 修改后的最大块数

    • 文件最多可以有:
      256 × 256 + 256 + 11 = 65,803 块
      • 解释:
        • 256 × 256:双重间接块支持的块数(256 个单重间接块,每个单重间接块支持 256 个数据块)。
        • 256:单重间接块本身支持的块数。
        • 11:剩下的直接块(从原来的 12 减去一个用于双重间接块指针)。

4. 可选任务:实现三重间接块(额外加分)

  • 三重间接块的工作方式:

    1. 每个 三重间接块 包含 256 个双重间接块的地址
    2. 每个双重间接块又指向 256 个单重间接块,每个单重间接块再指向 256 个数据块。
    3. 结果是一个文件的块数可以大幅提升,达到: 256 × 256 × 256 + 256 × 256 + 256 + 11
  • 加分实现建议

    • 三重间接块的实现逻辑与双重间接块类似,主要是增加一层指针解析。
    • 对文件系统性能要求更高,可以在完成双重间接块后尝试实现。

总结

  • 目标任务
    • 修改文件系统的 inode 结构,增加对 双重间接块 的支持,从而提升文件系统的最大文件大小到 65803 块。
  • 额外加分任务
    • 在双重间接块的基础上实现 三重间接块,进一步提升文件系统的支持能力。

以下是这段说明的翻译和解析,帮助你理解所需的定义和结构的作用:


定义与说明

阅读参考:
  • 如需详细信息,可参阅《xv6-book》第 8.10 节。
  • 根据以上提示和定义,代码中提供了修改后的结构,请仔细阅读代码中的注释。

修改后的定义(kernel/fs.h 中的宏定义)

  1. 宏定义解释
    • #define NDIRECT 11

      • 直接块的数量从 12 减少到 11
      • 这是因为第 12 个直接块的位置被牺牲,改为存储 双重间接块指针
    • #define NINDIRECT (BSIZE / sizeof(uint))

      • 表示单重间接块中可以存储的块指针数量。
      • 计算公式:BSIZE / sizeof(uint),即 1024 / 4 = 256
    • #define DNINDIRECT (NINDIRECT * NINDIRECT)

      • 表示双重间接块可以存储的数据块数量。
      • 计算公式:256 × 256 = 65536
    • #define MAXFILE (NDIRECT + NINDIRECT + DNINDIRECT)

      • 表示一个文件的最大块数(直接块 + 单重间接块 + 双重间接块)。
      • 计算公式:11 + 256 + 65536 = 65803

修改后的结构(kernel/fs.h 中的 dinode

  1. struct dinode 的定义
    • 作用:表示磁盘上的 inode 结构,包含文件的元信息和块指针。
    • 关键字段解释:
      • short type:文件类型。
      • short major:主设备号(仅适用于设备文件)。
      • short minor:次设备号(仅适用于设备文件)。
      • short nlink:文件链接数(硬链接数量)。
      • uint size:文件的大小(以字节为单位)。
      • uint addrs[NDIRECT + 2]
        • addrs 是块地址数组:
          • 前 11 个地址是直接块指针。
          • 第 12 个地址是单重间接块指针。
          • 第 13 个地址是双重间接块指针(新增)。

修改后的结构(kernel/file.h 中的 inode

  1. struct inode 的定义
    • 作用:表示内存中的 inode 结构,是 dinode 的内存副本。
    • 关键字段解释:
      • uint dev:设备号。
      • uint inum:inode 编号。
      • int ref:引用计数。
      • struct sleeplock lock:锁,用于保护结构中其他字段的并发访问。
      • int valid:是否已从磁盘加载。
      • uint addrs[NDIRECT + 2]
        • dinode 中的 addrs,用于存储直接块、单重间接块和双重间接块的指针。

修改注意事项

  1. 修改说明

    • 结构不可更改:上述的结构(dinodeinode)已提供,请勿修改
    • 仅在 TODO 标记部分实现逻辑。
  2. 关键变化总结

    • 直接块减少到 11:因为要为双重间接块腾出位置。
    • 新增双重间接块支持:在 addrs 的最后一个位置存储双重间接块的指针。

//TODO

 

这一块主要是定义了文件系统中 inode 结构 和一些与块分配相关的宏,用于支持你在作业中实现对大文件的管理。下面是逐步解释,让你更容易理解它们的作用:


什么是 inode?

inode(索引节点)是文件系统中用来描述文件的一个核心数据结构。它不是存储文件内容本身,而是存储文件的元信息,比如:

  • 文件的类型(普通文件、目录、设备文件等)
  • 文件的大小
  • 文件的块地址(指向实际存储数据的位置)

在这个作业中,你要修改 xv6 的 inode 结构以支持 双重间接块,从而使文件系统能管理更大的文件。


宏定义的作用

  1. NDIRECT

    • 表示直接块的数量。
    • 直接块是 inode 中直接指向数据块的指针。
    • 默认情况下是 12,但为了支持双重间接块,作业中改成了 11,把最后一个位置用于双重间接块指针。
  2. NINDIRECT

    • 表示单重间接块中可以存储的块地址数量。
    • 单重间接块是 inode 指向的一个中间块,这个块不存放数据,而是存储其他块的地址。
    • 计算公式是:
      NINDIRECT = BSIZE / sizeof(uint)
      其中 BSIZE = 1024sizeof(uint) = 4,所以 NINDIRECT = 1024 / 4 = 256
  3. DNINDIRECT

    • 表示双重间接块中可以存储的块地址数量。
    • 双重间接块是一个两级指针:
      • 第一层存储指向单重间接块的地址(256 个)。
      • 每个单重间接块又存储 256 个数据块的地址。
      • 计算公式是:
        DNINDIRECT = NINDIRECT * NINDIRECT = 256 × 256 = 65536
  4. MAXFILE

    • 表示一个文件能使用的最大块数,包括:
      • 11 个直接块。
      • 256 个单重间接块。
      • 65536 个双重间接块。
    • 计算公式是:
      MAXFILE = NDIRECT + NINDIRECT + DNINDIRECT = 11 + 256 + 65536 = 65803

dinodeinode 结构

1. dinode(磁盘上的 inode)
  • 作用:这是保存在磁盘上的 inode 结构,记录文件的元信息和块指针。
  • 字段解释
    • uint addrs[NDIRECT + 2]
      • 存储文件块的指针数组:
        • 前 11 个是直接块指针。
        • 第 12 个是单重间接块指针。
        • 第 13 个是双重间接块指针。

2. inode(内存中的 inode)
  • 作用:这是加载到内存中的 inode 结构,用于操作文件时临时存储。
  • 字段解释
    • uint addrs[NDIRECT + 2]
      • 同样存储直接块、单重间接块和双重间接块指针。

总结:这部分的重点

  • 你需要了解的变化

    • NDIRECT 从 12 改为 11,用于给双重间接块腾出空间。
    • addrs[NDIRECT + 2]
      • 现在包含了双重间接块指针(第 13 个位置)。
  • 这些定义和结构不需要修改

    • 它们是预先提供的基础代码,已经为你实现了双重间接块所需的结构调整。
  • 你的任务

    • 在作业中,围绕这些结构实现双重间接块的逻辑,包括数据块分配、释放、读取和写入。

 

块管理相关 API 的详细说明


Block Management(块管理)

文件系统中的块管理是核心部分,用来分配、释放、读取和写入磁盘块。这些 API 主要分为以下几类:

  1. 定义在 fs.c 中的块操作函数
  2. 定义在 bio.c 中的缓冲区操作函数
  3. 定义在 log.c 中的日志记录函数

1. 块管理函数(定义在 fs.c
1.1 bzero(int dev, int bno)
  • 作用:将指定的磁盘块清零(所有内容置为 0)。
  • 参数
    • dev:设备号,表示在哪个设备上执行操作。
    • bno:块号,表示要清零的块。
  • 比喻:这就像你借了一本旧书(磁盘块),需要先擦掉上面的字迹(清零)再开始使用。

1.2 uint balloc(uint dev)
  • 作用:分配一个新的磁盘块,并将其内容清零。
  • 返回值
    • 成功时返回新分配块的块号。
    • 如果磁盘空间不足,返回 0。
  • 比喻:这就像向图书管理员申请一本空白的新书。如果图书馆满了(磁盘空间不足),就无法分配。

1.3 void bfree(int dev, uint b)
  • 作用:释放一个指定的磁盘块,使其可以被其他文件使用。
  • 参数
    • dev:设备号。
    • b:要释放的块号。
  • 比喻:这就像你还书(释放块),让图书管理员把它放回书架,其他人可以借用。

2. 缓冲区管理函数(定义在 bio.c
2.1 struct buf* bread(uint dev, uint blockno)
  • 作用:从磁盘读取指定块到缓冲区,并返回一个已锁定的缓冲区对象。
  • 返回值:返回一个指向缓冲区对象的指针。
  • 比喻:这就像从仓库(磁盘)把一本书拿到借阅区(缓冲区),并锁定它以防止其他人同时访问。

2.2 void brelse(struct buf *b)
  • 作用:释放缓冲区对象,将其移动到最近使用列表的头部,表示可以被其他进程使用。
  • 参数
    • b:指向缓冲区对象的指针。
  • 比喻:这就像你看完书后,把书放回借阅区的书架上,让其他人可以继续借阅。

3. 日志管理函数(定义在 log.c
3.1 void log_write(struct buf *b)
  • 作用:将缓冲区中的数据标记为已修改,并记录日志以便稍后写入磁盘。
  • 典型用法
    1. 调用 bread() 获取缓冲区。
    2. 修改缓冲区中的数据。
    3. 调用 log_write() 记录修改。
    4. 调用 brelse() 释放缓冲区。
  • 比喻:这就像你拿到一本书后,在书上做笔记,然后告诉管理员这些修改需要最终保存到书里。

API 使用场景

这些 API 是实现文件系统操作的基础模块,具体用法如下:

  1. 分配和释放磁盘块

    • 使用 balloc() 分配一个新的磁盘块,并自动清零。
    • 使用 bfree() 释放一个不再需要的磁盘块。
  2. 读取和操作磁盘块

    • 使用 bread() 从磁盘读取块到缓冲区。
    • 修改缓冲区数据后,使用 log_write() 标记为已修改。
    • 使用 brelse() 释放缓冲区。
  3. 清零磁盘块

    • 使用 bzero() 将一个磁盘块的内容清零。

总结:API 的关系与比喻

  • 分配块

    • balloc() 就像借一本新书,同时自动清空书页内容。
    • bfree() 就像还书,让其他人可以使用。
  • 操作块

    • bread() 就像从仓库把书拿到借阅区,锁定它以防止冲突。
    • 修改书后,使用 log_write() 记录你的修改,并稍后保存到仓库。
    • brelse() 就是看完书后,放回借阅区供其他人使用。

下面是包含具体代码的内容以及每行代码的注释和比喻说明:


块管理代码

定义在 fs.c
// 将指定的磁盘块清零(将块内容全部置为 0)
static void bzero(int dev, int bno) {struct buf *bp = bread(dev, bno); // 从磁盘读取块 bno 到缓冲区memset(bp->data, 0, BSIZE);      // 将缓冲区中的数据清零log_write(bp);                   // 标记缓冲区为已修改,记录日志brelse(bp);                      // 释放缓冲区
}

逐行说明:

  1. bread(dev, bno):从设备号 dev 中读取块号 bno 的内容到缓冲区 bp
    • 比喻:从仓库(磁盘)取出书(块)到借阅区(缓冲区)。
  2. memset(bp->data, 0, BSIZE):将缓冲区的数据清零。
    • 比喻:把书的内容擦掉,变成一本空白的书。
  3. log_write(bp):记录这次清零操作,稍后写回磁盘。
    • 比喻:告诉管理员这本书已经被清零了,需要保存到仓库。
  4. brelse(bp):释放缓冲区。
    • 比喻:把书放回借阅区的书架上,供其他人使用。

// 分配一个新的磁盘块,并清零其内容
static uint balloc(uint dev) {for (int b = 0; b < FSSIZE; b++) {        // 遍历磁盘所有块if (block_is_free(dev, b)) {         // 如果块 b 是空闲的bzero(dev, b);                   // 将块 b 的内容清零mark_block_used(dev, b);         // 将块 b 标记为已使用return b;                        // 返回新分配的块号}}return 0;                                // 如果没有可用的块,返回 0
}

逐行说明:

  1. 遍历块:通过循环遍历磁盘中的每个块。
    • 比喻:管理员在整个仓库中寻找空白的书架。
  2. block_is_free(dev, b):检查块是否是空闲的。
    • 比喻:检查这个书架是否没有放书。
  3. bzero(dev, b):将空闲块的内容清零。
    • 比喻:如果书架是空的,先清空上面的灰尘。
  4. mark_block_used(dev, b):将块标记为已使用。
    • 比喻:在记录本上标注这本书(块)已经借出去。
  5. 返回块号:如果找到空闲块,返回其编号。

// 释放一个磁盘块
static void bfree(int dev, uint b) {clear_block_usage(dev, b);   // 将块 b 标记为未使用
}

逐行说明:

  1. clear_block_usage(dev, b):将块号 b 标记为未使用。
    • 比喻:把书架上的书还给图书馆,标记这个书架可以再次使用。

定义在 bio.c
// 从磁盘读取指定块到缓冲区,并返回缓冲区对象
struct buf* bread(uint dev, uint blockno) {struct buf *bp = buffer_cache_find(dev, blockno); // 在缓存中查找块if (!bp) {                                      // 如果缓存中没有bp = buffer_cache_allocate(dev, blockno);   // 分配一个新的缓冲区disk_read(dev, blockno, bp->data);          // 从磁盘读取块数据到缓冲区}lock_buffer(bp);                                // 锁定缓冲区,防止其他进程访问return bp;                                      // 返回缓冲区
}

逐行说明:

  1. buffer_cache_find(dev, blockno):先查找缓存中是否已有该块。
    • 比喻:管理员先在借阅区(缓存)找这本书,看是否已经有人借出。
  2. buffer_cache_allocate(dev, blockno):如果缓存中没有,则分配一个新的缓冲区。
    • 比喻:如果书不在借阅区,就分配一个新空位来存储这本书。
  3. disk_read(dev, blockno, bp->data):从磁盘读取块号为 blockno 的数据到缓冲区。
    • 比喻:从仓库(磁盘)搬运书到借阅区。
  4. lock_buffer(bp):锁定缓冲区,防止其他进程访问。
    • 比喻:管理员锁定书本,防止被多个人同时借走。

// 释放缓冲区
void brelse(struct buf *b) {unlock_buffer(b);          // 解锁缓冲区move_to_recent_list(b);    // 将缓冲区放到最近使用列表的头部
}

逐行说明:

  1. unlock_buffer(b):解锁缓冲区。
    • 比喻:管理员解锁书本,允许其他人查看。
  2. move_to_recent_list(b):将缓冲区移到最近使用列表头部。
    • 比喻:把书放到书架前排,方便下次快速找到。

定义在 log.c
// 记录缓冲区的修改,稍后写入磁盘
void log_write(struct buf *b) {pin_buffer(b);             // 增加缓冲区的引用计数,防止被替换mark_buffer_dirty(b);      // 标记缓冲区为已修改log_commit_buffer(b);      // 将修改记录到日志中
}

逐行说明:

  1. pin_buffer(b):增加引用计数,防止缓冲区被替换。
    • 比喻:管理员标注这本书暂时不能借出,还在修改中。
  2. mark_buffer_dirty(b):标记缓冲区内容为脏数据,表示需要写回磁盘。
    • 比喻:书已经被修改,管理员需要保存笔记。
  3. log_commit_buffer(b):将缓冲区的修改记录到日志。
    • 比喻:管理员记录修改内容,稍后存档。

总结

  • 这些 API 构成了文件系统中 磁盘块管理和缓存机制 的基础逻辑。
  • 它们的主要功能是:
    1. 分配、释放块fs.c):申请和回收磁盘上的存储空间。
    2. 缓存管理bio.c):从磁盘读取数据到内存,并提供缓存机制。
    3. 日志记录log.c):跟踪缓冲区的修改,确保数据一致性。

 

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

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

相关文章

Android 14之HIDL转AIDL通信

Android 14之HIDL转AIDL通信 1、interface接口1.1 接口变更1.2 生成hidl2aidl工具1.3 执行hidl2aidl指令1.4 修改aidl的Android.bp文件1.5 创建路径1.6 拷贝生成的aidl到1和current1.7 更新与冻结版本1.8 编译模块接口 2、服务端代码适配hal代码修改2.1 修改Android.bp的hidl依…

数据结构代码合集

一、排序算法 1、插入排序 1.1 直接插入排序 void InsertSort(int A[],int n){int temp,i,j; for( i 1;i<n;i){ //外循环&#xff0c;每个元素都要进行排序 if(A[i-1]>A[i]){ //前面元素比后面元素大的话 temp A[i];for( j i-1; A[j]>temp && j>0…

《硬件架构的艺术》笔记(九):电磁兼容性能设计指南

简介 电子线路易于接收来自其他发射器的辐射信号&#xff0c;这些EMI&#xff08;电磁干扰&#xff09;使得设备内毗邻的元件不能同时工作。这就有必要进行电磁兼容设计以避免系统内有害的电磁干扰。 确保设备不产生多余的辐射&#xff0c;设备也不易受到射频辐射的干扰&…

Anaconda安装(2024最新版)

安装新的anaconda需要卸载干净上一个版本的anaconda&#xff0c;不然可能会在新版本安装过程或者后续使用过程中出错&#xff0c;完全卸载干净anaconda的方法&#xff0c;可以参考我的博客&#xff01; 第一步&#xff1a;下载anaconda安装包 官网&#xff1a;Anaconda | The O…

【SpringBoot问题】IDEA中用Service窗口展示所有服务及端口的办法

1、调出Service窗口 打开View→Tool Windows→Service&#xff0c;即可显示。 2、正常情况应该已经出现SpringBoot&#xff0c;如下图请继续第三步 3、配置Service窗口的项目启动类型。微服务一般是Springboot类型。所以这里需要选择一下。 点击最后一个号&#xff0c;点击Ru…

力扣,88. 合并两个有序数组

我的思路是先单独对 数组2 做快排&#xff0c;但是快排的最差性能是 o(n^2) &#xff0c; 题目要求性能是 o( mn) 。 哦哦&#xff0c;不对不对&#xff0c; 它这数组给的就是有序的了&#xff1f; 麻蛋&#xff0c; 不需要排序了。 那就是 一开始最简单的思路&#xff0c; 直接…

Jmeter测试工具的安装和使用,mac版本,jmeter版本5.2.1

Jmeter测试工具的安装和使用JSON格式请求 一、安装1、安装jdk包和设置java环境2、去官网下载Jmeter3、解压后&#xff0c;打开mac终端&#xff0c;进入apache-jmeter的bin文件开启jmeter 二、使用jmeter1、添加线程2、添加HTTP请求3、配置请求的协议、IP地址、端口号、请求方法…

Cookie跨域

跨域&#xff1a;跨域名&#xff08;IP&#xff09; 跨域的目的是共享Cookie。 session操作http协议&#xff0c;每次既要request&#xff0c;也要response&#xff0c;cookie在创建的时候会产生一个字符串然后随着response返回。 全网站的各个页面都会带着登陆的时候的cookie …

多项式加法运算的链表实现

多项式加法运算的链表实现 主要思路&#xff1a;相同指数的项系数相加&#xff0c;其余部分进行拷贝。 两个多项式分别使用单链表实现&#xff0c;链表的每一个节点的结构为&#xff1a;系数、指数、下一个节点的地址。 链表节点按照指数递减顺序排列。 一句话&#xff1a;…

【N 卡 掉驱动 Driver 】NVML ERROR: Driver Not Loaded

问题描述 输入 nvitop 时报错 NVML ERROR: Driver Not Loaded&#xff0c;重启问题依旧存在。 问题解决-重新下载驱动 进入官网选择合适自己的驱动版本 https://www.nvidia.cn/geforce/drivers/ 根据个人情况搜索后&#xff0c;选择最新的 Driver 进行下载&#xff0c;如果希…

杭州网世一站式网络解决方案,助力安邦护卫网络升级改造

随着信息技术的不断进步&#xff0c;浙江台州安邦护卫有限公司现有的网络设备已无法满足其日益增长的业务需求。网络性能瓶颈、安全隐患和管理复杂性等问题逐渐凸显&#xff0c;严重影响了企业的运营效率和服务质量。为了解决这些问题&#xff0c;浙江台州安邦护卫有限公司决定…

IIC和SPI的时序图

SCL的变化快慢决定了通信速率&#xff0c;当SCL为低电平的时候&#xff0c;无论SDA是1还是0都不识别&#xff1a; ACK应答&#xff1a;当从设备为低电平的时候识别为从设备有应答&#xff1a; 谁接收&#xff0c;谁应答&#xff1a; 起始位和停止位&#xff1a; IIC的时序图&am…

C底层 函数栈帧

文章目录 一&#xff0c;什么是寄存器 二&#xff0c;栈和帧 前言 我们在学习c语言程序的时候&#xff0c;是不是有很多的疑问&#xff0c;如 1&#xff0c;为什么形参不可以改变实参 2&#xff0c;为什么我们编写程序的时候会出现烫烫烫......这个乱码 3&#xff0c;那些局…

全桥LLC变换器原理及MATLAB仿真模型

“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主电路拓扑 全桥LLC 谐振变换器主电路拓扑结构图。图中S1 &#xff5e; S4为功率开关管&#xff0c; D1 &#xff5e; D4为功率开关管的体二极管&#xff0c; C1 &#xff5e; C4 为功率开关管的寄生电容。谐振电感r…

TavilySearchResults报错

报错 pydantic_core._pydantic_core.ValidationError: 1 validation error for TavilySearchAPIWrapper Value error, Did not find tavily_api_key, please add an environment variable TAVILY_API_KEY which contains it, or pass tavily_api_key as a named parameter. …

物料理解笔记·蓝白段子线·端子线座子焊接反了怎么处理!!!

目录 蓝白端子排线 端子线座子焊接错了怎么办 端子线如何拆线 编写不易&#xff0c;请勿搬运&#xff0c;仅供学习&#xff0c;感谢理解 蓝白端子排线 蓝白端子排线&#xff0c;这种端子线常用与编码电机的接线&#xff0c;或者在板子上通过提供段子线的接口&#xff0c;通…

shell(8)until循环以及函数基本创建

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

51c自动驾驶~合集35

我自己的原文哦~ https://blog.51cto.com/whaosoft/12206500 #纯视觉方案的智驾在大雾天还能用吗&#xff1f; 碰上大雾天气&#xff0c;纯视觉方案是如何识别车辆和障碍物的呢&#xff1f; 如果真的是纯纯的&#xff0c;特头铁的那种纯视觉方案的话。 可以简单粗暴的理解为…

【ArcGIS Pro实操第11期】经纬度数据转化成平面坐标数据

经纬度数据转化成平面坐标数据 数据准备ArcGIS操作步骤-投影转换为 Sinusoidal1 投影2 计算几何Python 示例 另&#xff1a;Sinusoidal (World) 和 Sinusoidal (Sphere) 的主要区别参考 数据准备 数据投影&#xff1a; 目标投影&#xff1a;与MODIS数据相同&#xff08;Sinu…

【Leecode】Leecode刷题之路第62天之不同路径

题目出处 62-不同路径-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 62-不同路径-官方解法 方法1&#xff1a;动态规划 思路&#xff1a; 代码示例&#xff1a;&#xff08;Java&…