(undone) MIT6.S081 2023 学习笔记 (Day11: LAB10 mmap)
url: https://pdos.csail.mit.edu/6.1810/2023/labs/mmap.html
任务0:讲义如下 (完成)
mmap和munmap系统调用允许UNIX程序对其地址空间进行精细控制。它们可用于进程间共享内存、将文件映射到进程地址空间,并作为用户级页面错误处理方案的一部分,例如课程中讨论的垃圾回收算法。在本实验中,您将向xv6添加mmap和munmap功能,重点关注内存映射文件。
The manual page (run man 2 mmap) shows this declaration for mmap:
void *mmap(void *addr, size_t len, int prot, int flags,int fd, off_t offset);
mmap 可以通过多种方式调用,但本实验仅需要实现与文件内存映射相关的部分功能。您可以假设 addr 始终为零,这意味着内核应自行决定文件的映射虚拟地址。mmap 会返回该地址,如果失败则返回 0xffffffffffffffff。len 是要映射的字节数,它可能与文件长度不同。prot 表示内存是否应映射为可读、可写和/或可执行;您可以假设 prot 是 PROT_READ 或 PROT_WRITE 或两者兼具。flags 可以是 MAP_SHARED(表示对映射内存的修改应写回文件)或 MAP_PRIVATE(表示不应写回文件),无需实现其他标志位。fd 是要映射的文件的打开文件描述符。您可以假设 offset 为零(即文件中的映射起始位置)。
即使映射相同 MAP_SHARED 文件的进程不共享物理页,也是允许的。
munmap 的手册页(运行 man 2 munmap)显示其声明如下:
int munmap(void *addr, size_t len);
munmap 应移除指定地址范围内的内存映射。如果进程修改了该内存区域且映射方式为 MAP_SHARED,则需先将修改内容写回文件。munmap 可能仅解除部分 mmap 映射区域,但可以假设其操作范围仅限于:从起始位置解除、从末尾解除,或解除整个区域(而不会在区域中间“打洞”解除部分映射)。
你需要实现足够的 mmap 和 munmap 功能,以确保 mmaptest 测试程序能够正常运行。如果 mmaptest 没有用到某个 mmap 的特性,你就不需要实现该特性。
When you’re done, you should see this output:
$ mmaptest
mmap_test starting
test mmap f
test mmap f: OK
test mmap private
test mmap private: OK
test mmap read-only
test mmap read-only: OK
test mmap read/write
test mmap read/write: OK
test mmap dirty
test mmap dirty: OK
test not-mapped unmap
test not-mapped unmap: OK
test mmap two files
test mmap two files: OK
mmap_test: ALL OK
fork_test starting
fork_test OK
mmaptest: all tests succeeded
$ usertests -q
usertests starting
...
ALL TESTS PASSED
$
以下是一些提示:
- 首先,将 _mmaptest 添加到 UPROGS 中,并添加 mmap 和 munmap 系统调用,以便编译 user/mmaptest.c。目前,只需从 mmap 和 munmap 返回错误。我们在 kernel/fcntl.h 中为您定义了 PROT_READ 等。运行 mmaptest,它将在第一个 mmap 调用失败。
- 在页面错误处理时懒加载页表。也就是说,mmap 不应分配物理内存或读取文件。相反,在 usertrap 中(或由 usertrap 调用的页面错误处理代码中)执行此操作,就像写时复制实验一样。懒加载的原因是为了确保对大文件的 mmap 快速,并且对大于物理内存的文件的 mmap 成为可能。
- 跟踪每个进程 mmap 映射的内容。定义一个与“应用程序的虚拟内存”讲座中描述的 VMA(虚拟内存区域)相对应的结构。这应该记录由 mmap 创建的虚拟内存范围的地址、长度、权限、文件等。由于 xv6 内核中没有内核内存分配器,因此可以声明一个固定大小的 VMA 数组,并根据需要从中分配。大小为 16 应该足够。
- 实现 mmap:在进程的地址空间中找到一个未使用的区域来映射文件,并将一个 VMA 添加到进程的映射区域表中。VMA 应该包含一个指向被映射文件的 struct file 的指针;mmap 应该增加文件的引用计数,以便在文件关闭时结构不会消失(提示:参见 filedup)。运行 mmaptest:第一个 mmap 应该成功,但是对 mmap-ed 内存的第一次访问将导致页面错误并杀死 mmaptest。
- 添加代码以使 mmap-ed 区域的页面错误分配一个物理页面的内存,将相关文件的 4096 字节读取到该页面,并将其映射到用户地址空间。使用 readi 读取文件,该文件需要一个偏移参数来读取文件(但是您将不得不锁定/解锁传递给 readi 的 inode)。不要忘记正确设置页面的权限。运行 mmaptest;它应该到达第一个 munmap。
- 实现 munmap:找到地址范围的 VMA 并取消映射指定的页面(提示:使用 uvmunmap)。如果 munmap 删除了之前 mmap 的所有页面,则应该减少相应 struct file 的引用计数。如果取消映射的页面已被修改并且文件被映射为 MAP_SHARED,则应将页面写回文件。查看 filewrite 以获取灵感。
- 理想情况下,您的实现只会写回程序实际修改的 MAP_SHARED 页面。RISC-V PTE 中的脏位(D)指示页面是否已被写入。但是,mmaptest 不会检查未修改的页面是否没有被写回;因此,您可以不查看 D 位就写回页面。
- 修改 exit 以取消映射进程的映射区域,就像调用了 munmap 一样。运行 mmaptest;mmap_test 应该通过,但可能不是 fork_test。
- 修改 fork 以确保子进程具有与父进程相同的映射区域。不要忘记增加 VMA 的 struct file 的引用计数。在子进程的页面错误处理程序中,分配一个新的物理页面而不是与父进程共享页面是可以的。后者会更酷,但需要更多的实现工作。运行 mmaptest;它应该通过 mmap_test 和 fork_test。
运行 usertests -q 以确保一切仍然正常工作。
任务1:解析 mmaptest 源码 (完成)
先修改 Makefile,运行 make qemu
结果如下:
可以看到报错没有 mmap 和 munmap 两个系统调用。
先来看 mmaptest.c 源码:
main 函数,测试分为 mmap_test 和 fork_test 两部分
int
main(int argc, char *argv[])
{mmap_test();fork_test();printf("mmaptest: all tests succeeded\n");exit(0);
}
makefile 函数,创建文件 f,里面含有 1.5 个内存页的 A
//
// create a file to be mapped, containing
// 1.5 pages of 'A' and half a page of zeros.
//
void
makefile(const char *f)
{int i;// n = 一个内存页能映射的块数int n = PGSIZE/BSIZE;// 删除文件 funlink(f);// 创建文件 fint fd = open(f, O_WRONLY | O_CREATE);if (fd == -1)err("open");// 设置内存 buf 为全 Amemset(buf, 'A', BSIZE);// write 1.5 page,即文件 f 拥有 1.5 个内存页的 Afor (i = 0; i < n + n/2; i++) {if (write(fd, buf, BSIZE) != BSIZE)err("write 0 makefile");}// 关闭文件if (close(fd) == -1)err("close");
}
_v1 用来验证映射的内存为 1.5 页 A 和 0.5 页 0
//
// check the content of the two mapped pages.
//
void
_v1(char *p)
{// 循环遍历两个页的所有字节,1.5个页为 A,0.5 个页为 0int i;for (i = 0; i < PGSIZE*2; i++) {if (i < PGSIZE + (PGSIZE/2)) {if (p[i] != 'A') {printf("mismatch at %d, wanted 'A', got 0x%x\n", i, p[i]);err("v1 mismatch (1)");}} else {if (p[i] != 0) {printf("mismatch at %d, wanted zero, got 0x%x\n", i, p[i]);err("v1 mismatch (2)");}}}
}
接下来看 mmap_test 源码:
做了以下测试:
1.检测 mmap 是否起作用,能否把文件内容映射到进程内存
2.检测 PROT_WRITE 是否可用
… (直接看源码里的注释吧,一共7个测试)
void
mmap_test(void)
{int fd;int i;const char * const f = "mmap.dur";printf("mmap_test starting\n");testname = "mmap_test";//// create a file with known content, map it into memory, check that// the mapped memory has the same bytes as originally written to the// file.//// 创建文件 f,内含 1.5 个内存页的 A 和 0.5 个内存页的 0makefile(f);if ((fd = open(f, O_RDONLY)) == -1)err("open (1)");printf("test mmap f\n");//// this call to mmap() asks the kernel to map the content// of open file fd into the address space. the first// 0 argument indicates that the kernel should choose the// virtual address. the second argument indicates how many// bytes to map. the third argument indicates that the// mapped memory should be read-only. the fourth argument// indicates that, if the process modifies the mapped memory,// that the modifications should not be written back to// the file nor shared with other processes mapping the// same file (of course in this case updates are prohibited// due to PROT_READ). the fifth argument is the file descriptor// of the file to be mapped. the last argument is the starting// offset in the file.//// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);// addr: 建议的映射起始地址,通常设为 NULL 让内核自动选择// length: 要映射的区域长度// prot: 内存保护标志,可以是以下值的组合:// PROT_READ: 可读// PROT_WRITE: 可写// PROT_EXEC: 可执行// PROT_NONE: 不可访问// flags: 映射类型和选项,常用值:// MAP_SHARED: 共享映射,修改会写回文件// MAP_PRIVATE: 私有映射,修改不会影响原文件(会读取文件上的内容,但不会修改原文件,也不会同步其它进程的更新)// MAP_ANONYMOUS: 匿名映射,不与文件关联// MAP_FIXED: 强制使用指定的地址// fd: 文件描述符,匿名映射时设为 -1// offset: 文件偏移量,通常为 0// 返回值:// 成功时返回映射区域的起始地址,失败返回 MAP_FAILED ((void *)-1)// 映射的进程内存起始地址由内核选择,映射长度为两个页,内存只读,私有映射,映射文件 f,偏移量为0char *p = mmap(0, PGSIZE*2, PROT_READ, MAP_PRIVATE, fd, 0);if (p == MAP_FAILED)err("mmap (1)");// 验证映射内存是否为 1.5 页A 和 0.5 页 0_v1(p);// int munmap(void *addr, size_t length); // 用于解除内存映射// addr: 映射区域的起始地址// length: 要解除映射的区域长度// 返回值// 成功返回 0,失败返回 -1// 解除刚才的映射if (munmap(p, PGSIZE*2) == -1)err("munmap (1)");printf("test mmap f: OK\n");printf("test mmap private\n");// should be able to map file opened read-only with private writable// mapping// 一样的映射,只是映射的内存的操作权限变成可读可写 (一个只读打开的文件应该能使用 mmap PRIVATE 创建可写的内存)p = mmap(0, PGSIZE*2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);if (p == MAP_FAILED)err("mmap (2)");if (close(fd) == -1)err("close (1)");// 验证映射内容是否正确_v1(p);// 对映射内存修改for (i = 0; i < PGSIZE*2; i++)p[i] = 'Z';if (munmap(p, PGSIZE*2) == -1)err("munmap (2)");printf("test mmap private: OK\n");printf("test mmap read-only\n");// 如果是只读打开这个文件,那么 mmap 不允许 PROT_WRITE 和 MAP_SHARED 同时存在// check that mmap doesn't allow read/write mapping of a// file opened read-only.if ((fd = open(f, O_RDONLY)) == -1)err("open (2)");p = mmap(0, PGSIZE*3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p != MAP_FAILED)err("mmap (3)");if (close(fd) == -1)err("close (2)");printf("test mmap read-only: OK\n");printf("test mmap read/write\n");// 检测:如果文件是可读可写打开的,那么就可以让 mmap 能读写它// 注意:这里 mmap 映射了三页// check that mmap does allow read/write mapping of a// file opened read/write.if ((fd = open(f, O_RDWR)) == -1)err("open (3)");p = mmap(0, PGSIZE*3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED)err("mmap (4)");if (close(fd) == -1)err("close (3)");// check that the mapping still works after close(fd)._v1(p);// write the mapped memory.for (i = 0; i < PGSIZE*2; i++)p[i] = 'Z';// unmap just the first two of three pages of mapped memory.if (munmap(p, PGSIZE*2) == -1)err("munmap (3)");printf("test mmap read/write: OK\n");printf("test mmap dirty\n");// 检查上一次测试的写入是否生效// check that the writes to the mapped memory were// written to the file.if ((fd = open(f, O_RDWR)) == -1)err("open (4)");for (i = 0; i < PGSIZE + (PGSIZE/2); i++){char b;if (read(fd, &b, 1) != 1)err("read (1)");if (b != 'Z')err("file does not contain modifications");}if (close(fd) == -1)err("close (4)");printf("test mmap dirty: OK\n");printf("test not-mapped unmap\n");// unmap the rest of the mapped memory.// 检测是否能分多次 unmap 去解除一次 mmap 的映射if (munmap(p+PGSIZE*2, PGSIZE) == -1)err("munmap (4)");printf("test not-mapped unmap: OK\n");printf("test mmap two files\n");// 检测是否能同时映射两个文件//// mmap two files at the same time.//int fd1;if((fd1 = open("mmap1", O_RDWR|O_CREATE)) < 0)err("open (5)");if(write(fd1, "12345", 5) != 5)err("write (1)");char *p1 = mmap(0, PGSIZE, PROT_READ, MAP_PRIVATE, fd1, 0);if(p1 == MAP_FAILED)err("mmap (5)");if (close(fd1) == -1)err("close (5)");if (unlink("mmap1") == -1)err("unlink (1)");int fd2;if((fd2 = open("mmap2", O_RDWR|O_CREATE)) < 0)err("open (6)");if(write(fd2, "67890", 5) != 5)err("write (2)");char *p2 = mmap(0, PGSIZE, PROT_READ, MAP_PRIVATE, fd2, 0);if(p2 == MAP_FAILED)err("mmap (6)");if (close(fd2) == -1)err("close (6)");if (unlink("mmap2") == -1)err("unlink (2)");if(memcmp(p1, "12345", 5) != 0)err("mmap1 mismatch");if(memcmp(p2, "67890", 5) != 0)err("mmap2 mismatch");if (munmap(p1, PGSIZE) == -1)err("munmap (5)");if(memcmp(p2, "67890", 5) != 0)err("mmap2 mismatch (2)");if (munmap(p2, PGSIZE) == -1)err("munmap (6)");printf("test mmap two files: OK\n");printf("mmap_test: ALL OK\n");
}
fork_test 源码如下:
在测试父子进程都调用 mmap 和 unmmap 时的影响
//
// mmap a file, then fork.
// check that the child sees the mapped file.
//
void
fork_test(void)
{int fd;int pid;const char * const f = "mmap.dur";printf("fork_test starting\n");testname = "fork_test";// 创建文件 f,映射文件两次 p1 p2// mmap the file twice.makefile(f);if ((fd = open(f, O_RDONLY)) == -1)err("open (7)");if (unlink(f) == -1)err("unlink (3)");char *p1 = mmap(0, PGSIZE*2, PROT_READ, MAP_SHARED, fd, 0);if (p1 == MAP_FAILED)err("mmap (7)");char *p2 = mmap(0, PGSIZE*2, PROT_READ, MAP_SHARED, fd, 0);if (p2 == MAP_FAILED)err("mmap (8)");// read just 2nd page.if(*(p1+PGSIZE) != 'A')err("fork mismatch (1)");// 子进程取消掉 p1 的映射if((pid = fork()) < 0)err("fork");if (pid == 0) {_v1(p1);if (munmap(p1, PGSIZE) == -1) // just the first pageerr("munmap (7)");exit(0); // tell the parent that the mapping looks OK.}// 等待子进程结束int status = -1;wait(&status);if(status != 0){printf("fork_test failed\n");exit(1);}// 检查 p1 p2 指向的映射内存里的内容是否不变// check that the parent's mappings are still there._v1(p1);_v1(p2);printf("fork_test OK\n");
}
任务2:完成作业 (doing)
TODO: here
相关文章:
(undone) MIT6.S081 2023 学习笔记 (Day11: LAB10 mmap)
url: https://pdos.csail.mit.edu/6.1810/2023/labs/mmap.html 任务0:讲义如下 (完成) mmap和munmap系统调用允许UNIX程序对其地址空间进行精细控制。它们可用于进程间共享内存、将文件映射到进程地址空间,并作为用户级页面错误处理方案的一部分&#x…...
7400MB/s5050TBW完美结合,全新希捷酷玩530R SSD体验评测
7400MB/s&5050TBW完美结合,全新希捷酷玩530R SSD体验评测 哈喽小伙伴们好,我是Stark-C~ 说到希捷酷玩530 SSD,很多硬核进阶玩家应该都知道,或者说正在使用(比如说我~)。 作为希捷大厂旗下高性能SSD的…...
【数据结构与算法】同余计算 哈希表与前缀和问题特征和模板化思路
加减乘负的类同余计算 加乘模情况 两数和模 : (a b) mod m (a mod m b mod m) mod m乘积模 : (a * b) mod m ((a mod m) * (b mod m)) mod m 加模证明如下 : a q1 * m r1 , b q2 * m r2则 a mod m r1 , b mod m r2(a b) mod m ((q1 q2) * m (r1 r2)) mod m …...
TS 交叉类型
很类似于接口继承啊 哈哈哈 使用type关键字声明交叉类型 // 声明交叉类型 type PersonDetail person & Contactlet theshy:PersonDetail { name:the shy,phone:马头 }交叉类型和接口实现对对象的类型注解的区别与联系 如果在接口继承时发生同名属性冲突会报不兼容的错…...
FreeRTOS学习系列·二值信号量
目录 1. 信号量的基本概念 2. 二值信号量 3. 应用场景 4. 运作机制 5. 信号量控制块 6. 常用信号量函数接口API 6.1 创建二值信号量 xSemaphoreCreateBinary() 6.2 信号量删除函数 vSemaphoreDelete() 6.3 信号量释放函数 6.3.1 xSemaphoreGive() 6.3.2 …...
二叉搜索树 AVL树 红黑树 的性质
二叉搜索树 如何判断一棵树是否是二叉搜索树? 1.方法一 左子树的所有节点值 < 当前节点值,右子树的所有节点值 > 当前节点值,左右子树也必须满足 。 2.方法二 中序遍历,得到的序列是有序的 红黑树 红黑树的性质 1.根…...
分析 Docker 磁盘占用
以下是分析 Docker 磁盘占用的详细步骤和工具指南,帮助开发者快速定位和清理冗余数据: 1. 查看 Docker 磁盘使用概览 docker system df 输出说明: TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 15 …...
LLM提示词设计及多轮对话优化策略在心理健康咨询场景中的应用研究
多轮对话策略:设计LLM提示词并优化多轮对话输出 LLM提示词设计及多轮对话优化策略在心理健康咨询场景中的应用研究 摘要 本文针对大语言模型(LLM)在心理健康问题咨询对话场景中的应用,系统研究提示词设计方法及多轮对话优化策略。通过分析提示词核心原理,构建包含任务指…...
Kubernetes(k8s)学习笔记(七)--KubeSphere 最小化安装
前情提要 可视化操作面板对于开发、运维绝对是提升工作效率的一大利器,因此很有必要搭建一套可视化操作来管理Kubernetes。 可视化面板有多种: 1.Kubernetes官方提供的默认面板:dashboard,用处不大,放弃;…...
面向对象与过程介绍
一、面向对象具体介绍 (1)基本概念 1.对象 在面向对象编程中,对象是对现实世界中事物的抽象,它具有状态(属性)和行为(方法)。在 TypeScript 中,我们可以通过类、接口等…...
UniGetUI 使用指南:轻松管理 Windows 软件(包括CUDA)
UniGetUI(前身为 WingetUI)是一款专门为 Windows 10(x64)和 Windows 11 系统打造的图形化包管理器界面工具。它集成了 Winget、Scoop、Chocolatey、Npm、Pip、Cargo、vcpkg、.NET Tool 和 PowerShell 等多种常用包管理器的功能&am…...
使用 NGINX 实现 HTTP Basic 认证ngx_http_auth_basic_module 模块
一、前言 在 Web 应用中,对部分资源进行访问控制是十分常见的需求。除了基于 IP 限制、JWT 验证、子请求校验等方式外,最经典也最简单的一种方式便是 HTTP Basic Authentication。NGINX 提供的 ngx_http_auth_basic_module 模块支持基于用户名和密码的基…...
014枚举之指针尺取——算法备赛
枚举是数据结构与算法中基本的操作,常用于解决序列的区间问题。算法界将"双指针"视为其重要分支,类似地当然还有"三指针",“四指针”,最常见的还是“双指针”,我认为它们应统称为“指针尺取”。 双…...
Python小酷库系列:bidict,可以双向查询的dict
bidict,可以双向查询的dict 基本使用创建双向字典正向查找(key → value)反向查找(value → key)添加新项删除项 进阶功能使用 ~ (.inverse)获取逆映射使用 namedbidict 创建具名双向字典批量更…...
Android Compose 中 CompositionLocal 的全面解析与最佳实践
CompositionLocal 在 Android Compose 中的详细总结 核心概念 CompositionLocal 是 Jetpack Compose 提供的一种隐式数据传递机制,允许数据在组件树中向下传递,而无需显式地通过每个 Composable 函数的参数传递。 两种创建方式 1. staticComposition…...
Qt开发:容器组控件的介绍和使用
文章目录 一、Group Box(分组框)1.1 QGroupBox 简介1.2 基本用法1.3 设置为可勾选(可启用/禁用子控件)1.4 信号与槽连接(监控勾选状态)1.5 布局示例(完整) 二、Scroll Areaÿ…...
JS逆向入门案例1——集思录登录
JS逆向入门案例1——集思录登录 前言声明网站流程分析总结 前言 由于这段时间本职工作比较繁忙,没有很多空余的时间去研究各大厂的加密风控了,想起来自己刚接触js逆向走过坎坷,所以决定出一期js入门案例分析,为刚接触js逆向的小伙…...
ARM子程序和栈
微处理器中的栈由栈指针指向存储器中的栈顶来实现,当数据项入栈时,栈 指针向上移动,当数据项出栈时,栈指针向下移动。 实现栈时需要做出两个决定:一是当数据项进栈时是向低位地址方向向上生 长(图a和图b&a…...
笔试专题(十五)
文章目录 排序子序列题解代码 消减整数题解代码 最长公共子序列(二)题解代码 排序子序列 题目链接 题解 1. 贪心 模拟 2. 1 2 3 2 2 应该是有两个排列子序列的,所以i n-1时ret 3. 把水平的位置和上升部分,水平位置和下降部分分为一个排列子序列 代…...
使用OpenCV 和 Dlib 进行卷积神经网络人脸检测
文章目录 引言1.准备工作2.代码解析2.1 导入必要的库2.2 加载CNN人脸检测模型2.3 加载并预处理图像2.4 进行人脸检测2.5 绘制检测结果2.6 显示结果 3.完整代码4.性能考虑5.总结 引言 人脸检测是计算机视觉中最基础也最重要的任务之一。今天我将分享如何使用dlib库中的CNN人脸检…...
某信服EDR3.5.30.ISO安装测试(一)
一、前言 1.某信服EDR3.5.30 以下简称“EDR3.5”,即统一端点安全管理系统aES(终端检测响应EDR), 官网最新版:aES6.0.1R2,可下载的最低版本:EDR3.7.11R3, 下载地址:统一端点安全管理系统aES-…...
Dify 快速构建和部署基于LLM的应用程序
本文先对Dify做一个初步的认识,然后以一个实际的简单金融问答案例,配置chatflow 工作流。 一、Dify简介 如果你是第一次接触Dify,可以先创建一个简单的聊天助手,初步感觉一下,Dify在构建聊天问答类应用的过程。 比如…...
精益数据分析(40/126):移动应用商业模式的关键指标与盈利策略
精益数据分析(40/126):移动应用商业模式的关键指标与盈利策略 在创业和数据分析的探索之路上,我们持续挖掘不同商业模式的内在规律,以寻求更好的发展机遇。今天,我们依旧秉持共同进步的理念,深…...
JavaScript 实现输入框的撤销功能
在 Web 开发中,为输入框添加撤销功能可以极大地提升用户体验,方便用户快速回滚到之前的输入状态。本文将通过一段简单的 HTML、CSS 和 JavaScript 代码,详细介绍如何实现输入框的撤销功能。 整体实现思路 利用 JavaScript 监听输入框的inpu…...
【C++】类和对象(一)
前言 类和对象第一部分知识包括定义访问限定符类域实例化this指针 本人其他文章:恋风诗 文章中的源码[gitte]:mozhengy 类和对象(一) 前言1. 类的定义引例1.1 类定义格式1.2 类的访问限定符1.3 类域 2. 实例化2.1 实例化概念2.2 …...
【Vue】Vue3源码解析与实现原理
个人主页:Guiat 归属专栏:Vue 文章目录 1. Vue 3 架构概览1.1 模块化设计1.2 整体流程 2. 响应式系统2.1 响应式原理2.2 ref 和 reactive2.3 依赖收集与触发更新 3. 渲染系统3.1 虚拟DOM设计3.2 渲染管线3.3 Patch算法与Diff优化 4. 组件系统4.1 组件创建…...
黑马点评day02(缓存)
2、商户查询缓存 2.1 什么是缓存? 前言:什么是缓存? 就像自行车,越野车的避震器 举个例子:越野车,山地自行车,都拥有"避震器",防止车体加速后因惯性,在酷似"U"字母的地形上飞跃,硬着陆导致的损害,像个弹簧一样; 同样,实际开发中,系统也需要"避震…...
数据库MySQL学习——day9(聚合函数与分组数据)
文章目录 1. 聚合函数1.1 COUNT() 函数1.2 SUM() 函数1.3 AVG() 函数1.4 MIN() 函数1.5 MAX() 函数 2. GROUP BY 子句2.1 使用 GROUP BY 进行数据分组2.2 结合聚合函数 3. HAVING 子句3.1 使用 HAVING 过滤分组数据3.2 HAVING 和 WHERE 的区别 4. 实践任务4.1 创建一个销售表4.…...
为React组件库引入自动化测试:从零到完善的实践之路
为什么我们需要测试? 我们的ReactTypeScript业务组件库已经稳定运行了一段时间,主要承载各类UI展示组件,如卡片、通知等。项目初期,迫于紧张的开发周期,我们暂时搁置了自动化测试的引入。当时团队成员对组件逻辑了如指…...
数据结构——算法复杂度
一、数据结构定义 数据结构(Data Structure)是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤,所以我们要学各式各样的数据结构,如:线性表、树、图、哈希…...
Vue3响应式原理那些事
文章目录 1 响应式基础:Proxy 与 Reflect1.1 Proxy 代理拦截1.2 Reflect 确保 `this` 指向正确1.2.1 修正 `this` 指向问题1.2.2 统一的操作返回值1.3 与 Vue2 的对比2 依赖收集与触发机制2.1 全局依赖存储结构:WeakMap → Map → Set2.2 依赖收集触发时机2.3 依赖收集核心实…...
记9(Torch
目录 1、Troch 1、Troch 函数说明举例torch.tensor()torch.arange()创建张量创建一个标量:torch.tensor(42)创建一个一维张量:torch.tensor([1, 2, 3])创建一个二维张量:torch.tensor([[1, 2], [3, 4]])生成一维等差张量:语法&am…...
机器学习模型训练模块技术文档
一、模块结构概览 import numpy as np from sklearn.model_selection import cross_validate, learning_curve from sklearn.pipeline import make_pipeline from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing imp…...
健康养生:从微小改变开始
养生不必大刀阔斧,几个微小改变,就能让健康慢慢扎根生活。晨起别急着洗漱,先花 5 分钟靠墙站立,拉伸脊柱、调整体态,唤醒身体。早餐把白米粥换成杂粮粥,搭配水煮蛋和一小碟凉拌黄瓜,营养更全面。…...
某信服EDR3.5.30.ISO安装测试(二)
一、物理机启动EDR 1、修复dracut 使用DiskGenius克隆虚拟磁盘到物理磁盘,将虚拟机移植到物理机,因为磁盘UUID变化等原因,首次默认启动失败,提示: Starting Dracut Emergency Shell... Warning:/dev/centos/root doe…...
Leetcode:回文链表
1、题目描述 给定一个链表的 头节点 head ,请判断其是否为回文链表。 如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。 示例 1: 输入: head [1,2,3,3,2,1] 输出: true 示例 2: 输入: head [1,2] 输出: …...
IL2CPP 技术深度解析
IL2CPP 是 Unity 开发的高性能脚本后端,它将 .NET 的中间语言 (IL) 转换为 C 代码,再编译为原生平台二进制文件。以下是 IL2CPP 的全面技术剖析。 一、架构设计原理 1. 整体编译流程 C# 源代码 → Roslyn 编译器 → IL (.NET DLL)→ IL2CPP 转换器 →…...
AI图片修复工具,一键操作,图片更清晰!
泛黄的老相册里藏着一座记忆博物馆,每张照片都是时光长河中的琥珀。祖父军装照上的折痕里藏着抗美援朝的故事,父母结婚照褪色的红唇映照着八十年代的风尚,童年抓拍照上模糊的身影正重演着我们成长的轨迹。这些承载着集体记忆的影像࿰…...
国内短剧 vs. 海外短剧系统:如何选择?2025年深度对比与SEO优化指南
在短剧市场爆发式增长的背景下,国内与海外短剧系统成为创业者与企业的热门选择。本文将从市场潜力、开发成本、内容创作、盈利模式及风险五大维度,结合最新行业数据与案例,深度解析两者的优劣势,助您做出最优决策。 一、市场前…...
linux crash工具详解
crash 是 Linux 系统中用于分析内核转储文件(如 vmcore 或 kdump 生成的 dump 文件)的核心工具。它结合了调试符号和内核数据结构,能够直观地查看崩溃时的系统状态。以下是其详细使用方法及核心功能解析: 一、安装与准备 1. 安装…...
Scala day6(Class,field,Single Object)
Foreword【こんにちは】 Today, we continue to learn Scala Language, though the Scala isn’t easy for Begainner, Big Data Technology need Scala Language, Spark【Distributed Calculation FrameWork】is based on Scala Language designed. I know the learning road…...
不小心把当前的环境变量路径覆盖掉怎么办
起因 配置环境变量(~/.bashrc)的时候没加:$PATH,导致 source ~/.bashrc之后只剩下刚刚配置的环境变量了。连vim都打不开 解决 添加临时环境变量export PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH再重新修改…...
unity TMP字体使用出现乱码方框
参考文章: Unity 设置默认字体(支持老版及新版TMP)_unity tmp字体-CSDN博客 原因是导入的项目package包没有连着tmp一起,这样在新工程中导入的tmp字体默认的是tmp自己的,解决方案就是替换成自己需要的tmp字体就行 替换…...
14.网络钓鱼实战
网络钓鱼实战 第一部分:网络钓鱼攻击详解第二部分:设计与分析钓鱼攻击第三部分:钓鱼攻击防范实践总结 目标: • 深入理解网络钓鱼攻击的实施过程 • 掌握设计和识别钓鱼攻击的技巧 • 通过模拟实践提升防范钓鱼攻击的能力 第一部分…...
pyqt写一个单片机配置界面
已经实现以下功能 1.可以选择单片机架构 2.选择完单片机架构后第二个框可以选择常见单片机型号 3.选择完常见单片机型号后第三个框可以选择内部资源如adc等(可以选择多个内部资源)4.选择完内部资源如adc等(可以选择多个内部资源)后…...
「Mac畅玩AIGC与多模态20」开发篇16 - 使用结构化输出字段控制后续流程示例
一、概述 本篇介绍如何在工作流中使用结构化输出字段作为判断依据,实现前后节点联动控制。通过执行 LLM 节点输出结构化 JSON,并使用其中的字段驱动后续判断节点执行不同路径,开发人员将掌握结构化字段在工作流中的引用方式与分支控制技巧。…...
Unity-Shader详解-其四
今天我们来聊Unity特有的表面着色器以及很少提到的几何着色器。 表面着色器 在前文关于光照的计算中,我们学会了很多:我们学习了一系列光照模型,比如专门针对漫反射的兰伯特模型和改进的半兰伯特模型,又比如由高光、漫反射和环境…...
Lua 元表和元方法
元表(Metatable)和元方法(Metamethod)是Lua中实现面向对象编程、操作符重载和自定义行为的重要机制。 元表 元表是一个普通的Lua表,可以附加到另一个表上,用于定义或修改该表的行为。每个表都可以有自己的元表。 setmetatable(tab,metatab) 将metatab设…...
GESP2024年3月认证C++八级( 第二部分判断题(6-10))
海伦公式参考程序: #include <iostream> #include <cmath> // 引入cmath库以使用sqrt函数using namespace std;double calculateTriangleArea(int a, int b, int c) {// 使用海伦公式double s (a b c) / 2.0; // 半周长return sqrt(s * (s - a) *…...
Nacos源码—3.Nacos集群高可用分析一
大纲 1.Nacos集群的几个问题 2.单节点对服务进行心跳健康检查和同步检查结果 3.集群新增服务实例时如何同步给其他节点 4.集群节点的健康状态变动时的数据同步 5.集群新增节点时如何同步已有服务实例数据 1.Nacos集群的几个问题 问题一:在单机模式下ÿ…...