操作系统_内存管理

news2024/11/15 23:50:00

这里写目录标题

  • 虚拟内存是什么
  • 为什么要有虚拟内存
  • 虚拟内存的实现方式
    • 1.分页
      • 查找过程
      • 页表的底层实现
    • 2.分段
      • 段表的底层实现
    • 3.段页式
  • 分段和分页有什么区别
  • 什么是交换空间
  • 物理地址、逻辑地址、有效地址、线性地址、虚拟地址
  • 页面替换算法
  • 什么是缓冲区溢出 有什么危害
  • malloc 是如何分配内存的
    • malloc实现原理

虚拟内存是什么

虚拟内存(Virtual Memory)是一种计算机系统内存管理技术。它允许程序和操作系统访问一个更大的、连续的地址空间,这个地址空间实际上是由物理内存(例如RAM)和辅助存储设备(如硬盘的交换空间)组成的。

虚拟内存的主要作用和特点包括:

  1. 内存抽象:虚拟内存为每个程序提供了一个连续的、独立的地址空间。程序员在编写代码时,不需要关心实际的物理内存布局和限制。这简化了程序设计和编码过程。

  2. 程序隔离:由于每个程序都有自己的虚拟内存空间,因此程序之间的内存访问是相互隔离的。这有助于提高系统的稳定性和安全性,防止一个程序错误地访问或修改其他程序的数据。

  3. 内存管理:虚拟内存允许操作系统更灵活地管理物理内存和辅助存储设备之间的数据交换。操作系统可以根据需要将不经常使用的内存页面(page)从物理内存移到硬盘上的交换空间(swap space),从而为其他程序和数据腾出物理内存空间。

  4. 内存利用率:虚拟内存技术可以提高物理内存的利用率。通过按需分配内存,操作系统可以在多个程序之间共享有限的物理内存资源,从而提高内存的使用效率。

  5. 按需加载:虚拟内存允许操作系统只加载程序的部分内容到物理内存中,而不是一次性加载整个程序。这可以加快程序的启动速度,并节省内存资源。

总之,虚拟内存是一种强大的内存管理技术,它简化了程序开发过程,提高了系统的性能、稳定性和安全性。

为什么要有虚拟内存

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序能够访问比物理内存更大的地址空间。虚拟内存的主要目的和优点如下:

  1. 内存抽象:虚拟内存将物理内存抽象成连续的地址空间,使得每个应用程序都有自己独立的地址空间。这样,程序员不需要关心物理内存布局,也不需要考虑内存碎片问题。

  2. 内存隔离:虚拟内存为每个进程提供了独立的地址空间,确保一个进程的内存访问不会影响到其他进程的内存。这提高了系统的稳定性和安全性。

  3. 内存管理灵活性:虚拟内存允许操作系统更灵活地管理内存资源。例如,操作系统可以将不常用的内存页面移出到磁盘上的交换空间(swap space),从而为其他更需要内存的进程腾出空间。这种技术称为“页面置换”或“交换”。

  4. 内存利用率提高:虚拟内存允许多个进程共享系统的物理内存。通过按需分配内存(即仅在进程需要时分配内存),虚拟内存提高了内存的利用率。

  5. 程序加载优化:虚拟内存允许操作系统按需加载程序的部分内容到内存中。例如,一个大型程序可能只需要加载一部分常用的代码和数据到内存,而不需要一次性加载整个程序。这使得程序启动更快,同时节省了内存资源。

总之,虚拟内存技术为计算机系统提供了更高效、安全和灵活的内存管理方式。它使程序开发者能够以更简单的方式编写代码,同时还提高了整个系统的性能和稳定性。

虚拟内存的实现方式

虚拟内存的实现依赖于硬件和操作系统的协同工作。以下是虚拟内存的主要实现方式:

1.分页

在操作系统中,分页(Paging)是一种内存管理技术,用于将虚拟内存空间分割成大小固定的块,称为“页”(Page)。同样地,物理内存也被划分为大小相同的块,称为“页框”(Page Frame)或“帧”(Frame)。操作系统通过页表(Page Table)来管理虚拟地址与物理地址之间的映射关系。

分页技术的主要目的是实现虚拟内存的概念,使得程序员不需要关心物理内存的实际分布和限制。程序可以在一个连续的虚拟地址空间中运行,而操作系统会负责将这些虚拟地址映射到物理内存中的实际地址。这种映射使得不同程序之间的内存空间隔离,避免了程序间的内存访问冲突。

分页技术具有以下优点:

  1. 内存利用率提高:通过分页,操作系统可以将物理内存中的碎片化空间合并使用,提高内存利用率。
  2. 内存保护:每个程序都在独立的虚拟地址空间中运行,避免了程序间的内存访问冲突,提高了系统的稳定性。
  3. 动态加载与换出:操作系统可以根据需要将程序的部分页加载到内存中或者将不再需要的页换出到磁盘上,实现内存的动态管理。

分页技术的缺点主要是性能损耗。因为每次访问内存时,都需要通过页表进行地址转换,这会导致一定的时间开销。为了减少这种开销,现代处理器通常配有高速缓存(如Translation Lookaside Buffer, TLB),用于存储最近使用过的虚拟地址与物理地址之间的映射关系,从而提高地址转换的速度。

查找过程

操作系统使用分页(paging)机制来管理内存和实现虚拟内存。在分页系统中,内存被划分为固定大小的单元,称为页(page)。同样,虚拟内存也被划分为与页大小相同的单元,称为页框(page frame)。操作系统使用一个叫做页表(page table)的数据结构来记录虚拟内存中的每个页对应的物理内存中的页框。

在分页系统中查找地址的过程如下:

  1. 计算虚拟地址:当程序访问内存时,它会生成一个虚拟地址。虚拟地址可以分为两部分:虚拟页号(virtual page number, VPN)和页内偏移(offset within the page)。

  2. 查找页表:操作系统为每个进程维护一个页表。页表中的每个条目(称为页表项,PTE)包含虚拟页号和对应的物理页框号(physical frame number, PFN)。操作系统使用虚拟页号作为索引在页表中查找对应的页表项。

  3. 检查页表项:找到页表项后,操作系统会检查该项是否有效。如果无效,说明该虚拟地址尚未映射到物理内存,操作系统需要执行缺页处理(如分配新的物理内存并更新页表项)。

  4. 计算物理地址:如果页表项有效,操作系统可以从中获取物理页框号。然后,将物理页框号和虚拟地址中的页内偏移组合起来计算出物理地址。

  5. 访问物理内存:最后,操作系统使用计算出的物理地址访问物理内存,读取或写入数据。

这个过程总结为以下步骤:

物理地址 = (PFN << page_size_bits) | offset

其中,PFN 是从页表项中获得的物理页框号,page_size_bits 是页大小的比特数(如 4KB 页大小对应 12 比特),offset 是虚拟地址中的页内偏移。

分页系统的设计使得操作系统可以在不同的物理内存位置分配虚拟内存,实现内存隔离和保护。同时,分页系统还支持实现虚拟内存的特性,如按需加载、内存共享等。

页表的底层实现

操作系统中页表的底层实现通常采用数组或者树形数据结构。具体实现取决于操作系统和硬件架构。

  1. 数组:在单级页表的实现中,通常使用数组作为底层数据结构。每个进程都有一个独立的页表,页表中的每个元素(页表项,PTE)对应一个虚拟页。操作系统通过虚拟页号(VPN)作为索引直接在数组中查找相应的物理页框号(PFN)。

  2. 树形数据结构:多级页表和部分硬件支持的页表实现(如 x86 架构的页目录和页表)通常采用树形数据结构。最常见的是二级页表,它将虚拟地址划分为两部分:一级页表索引(P1)和二级页表索引(P2)。操作系统首先使用 P1 查找一级页表,然后使用 P2 查找二级页表。最后,从二级页表中找到的页表项包含物理页框号。多级页表可以进一步扩展为三级、四级等更多级别的树形结构,以适应更大的地址空间。

这些数据结构通常与硬件紧密相关,现代处理器往往提供硬件支持的页表实现,以加速虚拟地址到物理地址的转换过程。例如,x86 架构中的页目录和页表,以及 ARM 架构中的转换表(Translation Tables)都是基于树形数据结构的硬件页表实现。

2.分段

在操作系统中,分段(Segmentation)是另一种内存管理技术,它将程序的虚拟内存空间划分为多个逻辑上独立的部分,称为“段”(Segment)。每个段都有一个独立的起始地址和长度。分段技术的主要目的是支持程序中的逻辑结构,例如代码段、数据段和栈段等,提高内存管理的灵活性。

分段技术的基本原理是将程序的逻辑地址(段号和段内偏移量)映射为物理内存中的实际地址。为了实现这种映射,操作系统使用了一种叫做段表(Segment Table)的数据结构。段表中的每个条目包含了一个段的基地址和长度,操作系统根据逻辑地址中的段号在段表中查找相应的基地址,然后将基地址和段内偏移量相加,得到物理地址。

分段技术具有以下优点:

  1. 支持程序的逻辑结构:分段允许程序员根据程序的逻辑结构(如代码、数据和栈等)来组织内存空间,提高了内存管理的灵活性。
  2. 内存保护:通过为每个段设置访问权限(如只读、可读写等),操作系统可以实现内存空间的保护,防止程序在运行过程中意外地修改了其他段的内容。
  3. 动态加载与卸载:操作系统可以根据需要动态地将程序的某个段加载到内存中,或者将不再需要的段卸载出内存,实现内存的动态管理。

然而,分段技术的主要缺点是内存碎片问题。由于段的大小不固定,当程序运行一段时间后,内存中可能会出现很多大小不一的空闲空间,导致内存利用率降低。为了克服这个问题,很多操作系统采用了分页和分段相结合的内存管理方案,充分利用了两种技术的优点。

[外链图片转存中...(img-EeHy81fy-1691238615233)]

段表的底层实现

在操作系统中,段表的底层实现通常采用数组作为数据结构。段表用于存储虚拟地址到物理地址的映射信息,以支持基于段的内存管理方式。

3.段页式

段页式虚拟内存结合了分段(Segmentation)和分页两种方法。在段页式系统中,虚拟地址空间首先被划分为多个独立的段(Segment),每个段可以有不同的大小和属性(如代码段、数据段等)。然后,每个段被进一步划分为固定大小的页。段页式虚拟内存允许程序员根据程序的逻辑结构分配内存,并提供了内存保护和共享的功能。段页式虚拟内存的实现需要硬件支持,如 x86 架构中的 Intel 80386 及以后的处理器。地址结构就由段号、段内页号和页内位移三部分组成。

段页式地址变换中要得到物理地址须经过三次内存访问:

  • 第一次访问段表,得到页表起始地址;
  • 第二次访问页表,得到物理页号;
  • 第三次将物理页号与页内位移组合,得到物理地址。

虚拟内存的实现需要硬件和操作系统的支持。例如,现代处理器通常包含内存管理单元(Memory Management Unit,MMU),用于处理虚拟地址到物理地址的转换和内存访问控制。操作系统负责管理页表、处理缺页中断、分配和回收内存等任务。

[外链图片转存中...(img-lkSbqlPG-1691238615235)]

分段和分页有什么区别

分段(Segmentation)和分页(Paging)都是内存管理技术,用于实现虚拟内存。它们之间的主要区别如下:

  1. 地址空间划分

    • 分段:将虚拟地址空间划分为多个不同大小的段(Segment),每个段具有自己的基址(Base Address)和界限(Limit)。段的大小取决于程序的逻辑结构,例如代码段、数据段和堆栈段。
    • 分页:将虚拟地址空间和物理地址空间都划分为固定大小的页(Page)。每个虚拟页可以映射到一个物理页或硬盘上的交换空间。页的大小通常是2的幂次方(如4KB、8KB等)。
  2. 内存映射方式

    • 分段:虚拟地址包含一个段选择器(Segment Selector)和一个偏移量(Offset)。物理地址是基址加上偏移量。分段的内存映射关系由段表(Segment Table)维护。
    • 分页:虚拟地址被划分为页号(Page Number)和页内偏移(Offset within Page)。物理地址由物理页号和页内偏移组成。分页的内存映射关系由页表(Page Table)维护。
  3. 内存分配和管理

    • 分段:内存分配基于段,每个段的大小可以根据需要动态调整。分段内存管理更符合程序的逻辑结构,但可能导致内存碎片问题。
    • 分页:内存分配基于页,页的大小是固定的。分页内存管理简化了内存分配和回收过程,减少了内存碎片问题,但可能导致内存浪费(部分页未被完全使用)。
  4. 内存保护和共享

    • 分段:每个段都有自己的访问权限和属性,如只读、可执行等。这有助于实现内存保护和共享。例如,多个程序可以共享一个只读的代码段。
    • 分页:虽然分页本身没有提供内存保护和共享功能,但许多分页系统通过扩展页表项来支持这些功能,例如页表项中的访问权限位和脏位(Dirty Bit)。

总之,分段和分页都是实现虚拟内存的方法,但它们在地址空间划分、内存映射方式、内存分配和管理以及内存保护和共享方面有所不同。现代操作系统通常采用分页或段页式虚拟内存(结合分段和分页的优点)。

什么是交换空间

交换空间(Swap Space)是计算机系统中用于支持虚拟内存管理的一种存储区域,通常位于硬盘或固态硬盘上。当物理内存(RAM)不足以容纳所有运行中的程序和数据时,操作系统会将一部分数据(通常是最近较少使用的页面或段)从物理内存移出到交换空间,从而为其他程序或数据腾出内存空间。这个过程被称为“交换”(Swapping)或“页面交换”(Page Swapping)。

交换空间的主要作用是扩展可用内存资源,使计算机系统能够运行更多的程序或处理更大的数据。然而,由于硬盘或固态硬盘的访问速度远低于物理内存,频繁发生交换操作会导致系统性能下降。因此,交换空间主要作为一种补充手段,而不是内存的替代品。

在不同的操作系统中,交换空间的具体实现方式可能有所不同。例如:

  • 在Linux和UNIX系统中,交换空间可以是一个专门的磁盘分区(Swap Partition)或一个交换文件(Swap File)。
  • 在Windows系统中,交换空间通常被称为“虚拟内存文件”或“页文件”(Page File),默认保存在系统分区的根目录下,文件名为 pagefile.sys。

为了提高系统性能,建议将交换空间放置在最快的硬盘上,并根据系统的内存使用情况调整交换空间的大小。在具有足够物理内存的现代计算机系统中,可以适当减少对交换空间的依赖以提高性能。

物理地址、逻辑地址、有效地址、线性地址、虚拟地址

这些地址类型都与内存管理和访问相关,它们之间的区别如下:

  1. 物理地址(Physical Address):物理地址是计算机硬件(如CPU和内存)用于访问内存的实际地址。它直接对应于物理内存(RAM)上的一个位置。在物理内存中,每个字节都有一个唯一的物理地址。

  2. 逻辑地址(Logical Address):逻辑地址是程序在编译时分配的地址,它表示程序内存访问的相对位置。逻辑地址与程序的逻辑结构相关,如代码段、数据段和堆栈段。在程序加载到内存并运行时,逻辑地址会被转换为实际的物理地址或虚拟地址。

  3. 有效地址(Effective Address):有效地址是CPU在执行指令时用于计算实际内存访问地址的中间结果。对于某些体系结构,有效地址可能需要与基址(Base Address)或段基址(Segment Base Address)相加以生成最终的物理地址或虚拟地址。

  4. 线性地址(Linear Address):线性地址是逻辑地址到物理地址转换过程中的一个中间层次,在分段内存管理系统中通常用于表示内存访问的位置。线性地址是一个单调递增的地址空间,它通过将段基址与逻辑地址相加来生成。在分段和分页联合使用的内存管理系统中,线性地址先经过段式地址转换得到,然后通过分页机制映射到物理地址。

  5. 虚拟地址(Virtual Address):虚拟地址是程序在运行时使用的地址,它通过内存管理单元(MMU)映射到物理地址。虚拟地址空间的大小通常比物理内存要大,这允许程序访问比实际物理内存更大的地址空间。虚拟地址的使用可以提高内存管理的灵活性和安全性。虚拟地址在分页内存管理系统中经常使用,它由页号(Page Number)和页内偏移(Offset within Page)组成。

总之,这些地址类型在内存管理和访问过程中扮演不同的角色。物理地址是实际的内存位置,而逻辑地址、线性地址和虚拟地址分别表示程序编译时、运行时的内存访问方式。有效地址则用于计算实际的内存访问地址。这些地址类型在不同的内存管理系统(如分段、分页或段页式)中可能有所不同。

页面替换算法

页面替换算法(Page Replacement Algorithm)是操作系统中用于选择哪个内存页面应该被替换出内存以释放空间,以便将所需的页面加载到内存中的一种策略。以下是几种常见的页面替换算法:

  1. 最佳页面替换算法(Optimal Page Replacement, OPT):最佳页面替换算法是一种理论上的算法,它选择最长时间内不会被访问的页面进行替换。由于这需要预知未来的内存访问模式,所以在实际应用中是不可行的。然而,OPT算法常作为其他页面替换算法性能的理想基准。

  2. 先进先出页面替换算法(First-In, First-Out, FIFO):FIFO算法选择最早加载到内存中的页面进行替换。这是一种简单且容易实现的算法,但可能导致较低的命中率,因为最早加载的页面可能仍然是经常访问的页面。

  3. 最近最少使用页面替换算法(Least Recently Used, LRU):LRU算法选择最长时间未被访问的页面进行替换。这是一种基于访问历史的算法,通常能够获得较好的性能。实际实现时,通常需要额外的数据结构(如链表、哈希表或时间戳)来记录页面的访问顺序。

  4. 时钟页面替换算法(Clock Page Replacement):时钟算法是一种近似LRU的算法,它维护一个循环链表,每个页面在链表中有一个对应的项,其中包含一个访问位(Access Bit)。当需要替换页面时,时钟算法从当前指针位置开始遍历链表,找到第一个访问位为0的页面进行替换。如果访问位为1,则将其置0并继续查找。这种方法可以在较低的开销下实现近似LRU的性能。

  5. 随机页面替换算法(Random Page Replacement):随机算法选择一个随机的页面进行替换。尽管这种方法可能导致较差的性能,但在某些情况下(如内存访问模式不具有局部性时),随机算法可能表现得比其他算法更好。

  6. 最不常用页面替换算法(Least Frequently Used, LFU):LFU算法选择访问频率最低的页面进行替换。这种方法试图捕捉页面的长期访问模式,但可能在短期内受到访问频率波动的影响。实现LFU通常需要维护一个访问计数器和一个额外的数据结构来按访问频率排序页面。

这些页面替换算法各有优缺点,具体选择哪种算法取决于系统的需求和内存访问模式。在实际应用中,操作系统可能采用不同的策略和优化手段来改进这些算法,以在保证性能的同时降低开销。

什么是缓冲区溢出 有什么危害

缓冲区溢出(Buffer Overflow)是一种程序漏洞,发生在程序试图向一个固定大小的缓冲区写入超出其容量的数据时。这通常发生在操作系统和应用程序处理输入数据时,没有正确检查数据长度,导致数据超出分配给缓冲区的内存空间。当缓冲区溢出发生时,超出缓冲区容量的数据会覆盖相邻的内存区域,可能导致程序崩溃或产生非预期的行为。

缓冲区溢出的危害主要表现在以下几个方面:

  1. 程序崩溃:当缓冲区溢出覆盖了重要的程序数据(如变量、函数指针等),可能导致程序执行错误或崩溃。这种情况下,用户可能会丢失正在处理的数据,或者需要重新启动程序。

  2. 数据破坏:缓冲区溢出可能导致程序数据被破坏或篡改。在某些情况下,攻击者可能利用这一点来修改程序的正常功能,如篡改数据库中的数据或更改程序的控制流程。

  3. 安全漏洞:缓冲区溢出是许多安全漏洞的根源,攻击者可能利用这一漏洞执行任意代码或绕过安全措施。例如,攻击者可能向缓冲区中插入恶意代码,并通过覆盖程序的返回地址或函数指针来执行该代码。这可能导致严重的安全问题,如信息泄露、权限提升或远程代码执行。

  4. 拒绝服务(Denial of Service, DoS)攻击:缓冲区溢出可能被用来发起拒绝服务攻击。攻击者可以通过发送特制的数据触发程序的缓冲区溢出,导致程序崩溃或无法正常提供服务。

为了防止缓冲区溢出,操作系统和应用程序开发者在编写代码时需要注意检查输入数据的大小,确保它不会超过缓冲区的容量。此外,编译器和操作系统也提供了一些机制(如栈保护、地址空间布局随机化(ASLR)等)来降低缓冲区溢出的危害。但是,防止缓冲区溢出的最根本方法还是编写安全、健壮的代码,避免出现此类漏洞。

malloc 是如何分配内存的

malloc 是 C 语言库函数,用于动态分配内存。其原型为:

void* malloc(size_t size);

在操作系统中,malloc 是一个库函数,通常由 C 语言运行时库(例如 glibc)提供。它用于在程序的堆区域动态分配内存。具体实现可能因操作系统和 C 库而异,但其基本工作原理大致相同。以下是 malloc 的一般工作流程:

  1. 初始化堆区域:在程序启动时,操作系统会为堆分配一定的内存空间,这个空间可以在运行过程中增加或减少。堆区域是程序运行时用于存储动态分配内存的区域。

  2. 内存池管理:为了提高分配效率,malloc 通常会维护一个内存池。这个内存池包含了一系列已经从操作系统获取的内存块。当调用 malloc 分配内存时,它会首先在内存池中查找合适的内存块,而不是直接向操作系统申请。

  3. 查找空闲内存块malloc 会在内存池中查找一个大小足够的空闲内存块。为了避免内存碎片,malloc 通常使用一些优化算法(如最佳适配、首次适配、伙伴系统等)来选择合适的内存块。

  4. 扩展堆:如果 malloc 在内存池中找不到合适的内存块,它会向操作系统申请更多的内存,扩展堆的大小。这通常通过系统调用(如 brkmmap)完成。操作系统会分配一块连续的虚拟内存空间,将其映射到物理内存,然后将其添加到内存池中。

  5. 分配内存块:一旦找到合适的内存块,malloc 会将其标记为已分配,并将其起始地址返回给调用者。

  6. 内存对齐:在分配内存时,malloc 通常会确保内存地址按照一定的边界对齐(如 8 字节或 16 字节对齐)。这有助于提高程序访问内存的性能,因为 CPU 可以更有效地访问对齐的内存地址。

需要注意的是,malloc 分配的内存是未初始化的,使用前需要手动初始化。使用完分配的内存后,需要调用 free 函数将内存归还给内存池,避免内存泄漏。

malloc实现原理

当开辟的空间小于 128K 时,调用 brk()函数;当开辟的空间大于 128K 时,调用mmap()。malloc采用的是内存池的管理方式,以减少内存碎片。先申请大块内存作为堆区,然后将堆区分为多个内存块。当用户申请内存时,直接从堆区分配一块合适的空闲快。采用隐式链表将所有空闲块,每一个空闲块记录了一个未分配的、连续的内存地址。

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

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

相关文章

Arthas协助MQ消费性能优化

背景 项目中使用AWS的SQS消息队列进行异步处理&#xff0c;QA通过压测发现单机TPS在23左右&#xff0c;目标性能在500TPS&#xff0c;所以需要对消费逻辑进行优化&#xff0c;提升消费速度。 目标 消费TPS从23提升到500 优化流程 优化的思路是先分析定位性能瓶颈&#xff…

如何加载模型YOLOv8 ONNXRuntime

YOLOv8 是 YOLO(You Only Look Once)目标检测系统的最新版本(v8)。YOLO 是一种实时、一次性目标检测系统,旨在在网络的单次前向传递中执行目标检测,使其快速高效。YOLOv8是之前YOLO模型的改进版本,具有更高的精度和更快的推理速度。 ONNX(开放神经网络交换)是一种表示…

算法练习--leetcode 数组

文章目录 爬楼梯问题裴波那契数列两数之和 [数组]合并两个有序数组移动零找到所有数组中消失的数字三数之和 爬楼梯问题 输入n阶楼梯&#xff0c;每次爬1或者2个台阶&#xff0c;有多少种方法可以爬到楼顶&#xff1f; 示例1&#xff1a;输入2&#xff0c; 输出2 一次爬2阶&a…

正点原子HAL库入门1~GPIO

探索者F407ZGT6(V3) 理论基础 IO端口基本结构 F4/F7/H7系列的IO端口 F1在输出模式&#xff0c;禁止使用内部上下拉 F4/F7/H7在输出模式&#xff0c;可以使用内部上下拉不同系列IO翻转速度不同 F1系列的IO端口 施密特触发器&#xff1a;将非标准方波&#xff0c;整形为方波 当…

WebRTC 之音视频同步

在网络视频会议中&#xff0c; 我们常会遇到音视频不同步的问题&#xff0c; 我们有一个专有名词 lip-sync 唇同步来描述这类问题&#xff0c;当我们看到人的嘴唇动作与听到的声音对不上的时候&#xff0c;不同步的问题就出现了 而在线会议中&#xff0c; 听见清晰的声音是优先…

pygame贪吃蛇游戏

pygame贪吃蛇游戏 贪吃蛇游戏通过enter键启动&#xff0c;贪吃蛇通过WSAD进行上下左右移动&#xff0c;每次在游戏区域中随机生成一个食物&#xff0c;每次吃完食物后&#xff0c;蛇变长并且获得积分&#xff1b;按空格键暂停。 贪吃蛇 import random, sys, time, pygame from …

SQL 表别名 和 列别名

列表名 列表名之后 order by 可以用别名 也可以用原名&#xff0c; where 中不能用别名的 SQL语句执行顺序&#xff1a; from–>where–>group by -->having — >select --> order 第一步&#xff1a;from语句&#xff0c;选择要操作的表。 第二步&#xff1…

SolidWorks 3D Interconnect介绍

目前市面上有的三维设计软件有很多&#xff0c;如UG、Pro/E、CATIA等&#xff0c;而且每个三维设计软件都会生成自己文件格式。由于产品设计的原因&#xff0c;我们避免不了的会需要去使用不同三维设计软件的文件&#xff0c;这对于工程师来说其实是一件比较麻烦的事。 为什么…

性能测试JMeter学习笔记(脚本增强和命令行操作)

HTTP的Cookie管理器 在根节点下&#xff0c;添加“HTTP Cookie管理器”&#xff08;注意是根节点&#xff09; Cookie管理器作用&#xff1a;只要响应里有Cookie&#xff0c;就自动存进Cookie管理器&#xff0c;而后在后续的请求中&#xff0c;自动携带cookie JMeter脚本增强…

奥威BI系统:零编程建模、开发报表,提升决策速度

奥威BI是一款非常实用的、易用、高效的商业智能工具&#xff0c;可以帮助企业快速获取数据、分析数据、展示数据。值得特别注意的一点是奥威BI系统支持零编程建模、开发报表&#xff0c;是一款人人都能用的大数据分析系统&#xff0c;有助于全面提升企业的数据分析挖掘效率&…

教资学习笔记总结

科目一 科目二 第一章 教育基础知识和基本原理 第一节 教育的认识 1.教育的概念 教育的词源&#xff1a;教育一词最早出现于《孟子尽心上》&#xff1a;“得天下英才而教育之”许慎在《说文解字》中最早解释教育&#xff1a;“教&#xff0c;上所施&#xff0c;下所效也”…

DNS部署与安全详解(上)

文章目录 一、DNS二、域名组成1. 域名组成概述2. 域名组成 三、监听端口四、DNS解析种类1. 按照查询方式分类&#xff1a;2. 按照查询内容分类&#xff1a; 五、DNS服务器搭建过程1. 先确保服务器的IP地址是固定的2. 安装DNS软件 一、DNS DNS全称Domain Name Service&#xff0…

组合总和——力扣39

文章目录 题目描述回溯题目描述 回溯 class Solution {public:vector<vector<

Qt--动态链接库的创建和使用

写在前面 在Qt的实际开发中&#xff0c;免不了使用和创建动态链接库&#xff0c;因此熟悉Qt中动态链接库的创建和使用对后续的库开发或使用是非常用必要的。 在之前的文章https://blog.csdn.net/SNAKEpc12138/article/details/126189926?spm1001.2014.3001.5501中已经对导入…

Swish - Mac 触控板手势窗口管理工具[macOS]

Swish for Mac是一款Mac触控板增强工具&#xff0c;借助直观的两指轻扫&#xff0c;捏合&#xff0c;轻击和按住手势&#xff0c;就可以从触控板上控制窗口和应用程序。 Swish for Mac又不仅仅只是一个窗口管理器&#xff0c;Swish具有28个易于使用的标题栏&#xff0c;停靠栏…

基于ffmpeg与SDL的视频播放库

由于工作需要&#xff0c;自己封装的基于ffmpeg的视频编解码库&#xff0c;显示采用了SDL库。可以播放本地文件或网络流&#xff0c;支持多端口播放&#xff0c;支持文字叠加&#xff0c;截图、视频录制等等。 头文件代码&#xff1a; #pragma once #ifdef __DLLEXPORT #defin…

Visual Studio在Debug模式下,MFC工程中包含Eigen库时的定义冲突的问题

Visual Studio在Debug模式下&#xff0c;MFC工程中包含Eigen库时的定义冲突的问题 报错信息 Eigen\src\Core\PlainObjectBase.h(143,5): error C2061: 语法错误: 标识符“THIS_FILE” Eigen\src\Core\PlainObjectBase.h(143,1): error C2333: “Eigen::PlainObjectBase::opera…

Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

文章目录 一、重映射简介二、图像扭曲 一、重映射简介 重映射&#xff0c;就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即&#xff1a; 在重映射过程中&#xff0c;图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系&#xff0c;因…

[MAUI]模仿微信“按住-说话”的交互实现

今天使用这个控件&#xff0c;做一个模仿微信“按住-说话”的小功能&#xff0c;最终效果如下&#xff1a; 使用.NET MAUI实现跨平台支持&#xff0c;本项目可运行于Android、iOS平台。 创建页面布局 新建.NET MAUI项目&#xff0c;命名HoldAndSpeak MainPage.xaml中创建一个…

【敏捷开发】测试驱动开发(TDD)

测试驱动开发&#xff08;Test-Driven Development&#xff0c;简称TDD&#xff09;是敏捷开发模式中的一项核心实践和技术&#xff0c;也是一种设计方法论。TDD有别于以往的“先编码&#xff0c;后测试”的开发模式&#xff0c;要求在设计与编码之前&#xff0c;先编写测试脚本…