第五章 保护模式进阶,向内核迈进

news2025/1/20 21:51:15

获取物理内存容量

学习Linux获取内存的方法

通过调用BIOS中断0x15实现,分别是BIOS中断0x15的三个子功能,子功能号要存放到寄存器EAX或AX中:
在这里插入图片描述

BIOS中断是实模式下的方法,只能进入保护模式前调用。可以在实模式下用这三种方法检测完内存容量后再进入保护模式。

BIOS中断可以返回已安装的硬件信息,由于BIOS及其中断也只是一组软件,它要访问硬件也要依靠硬件提供的接口。所以,获取内存信息,其内部是通过连续调用硬件的应用程序接口(API)来获取内存信息的

利用BIOS中断0x15子功能0xe820获取内存

BIOS中断0x15子功能0xe820能够获取系统的内存布局。
系统内存各部分的类型属性不同,BIOS按照类型属性划分这片系统内存,在查询时也是按类型返回内存信息。子功能0xe820能够返回多个属性字段。

地址范围描述符结构(ARDS)用于存储描述内存信息内容的地址范围描述符。每次int 0x15之后,BIOS就会返回这样一个结构的数据,这个数据描述了一个类型的内存范围信息。正常情况下,不会出现较大的内存区域不可用情况,所以在所有返回的ARDS结构里,此值最大的内存块一定是操作系统可使用的部分,即主板上配置的物理内存

在这里插入图片描述

BIOS中断0x15子功能0xe820调用方法:

  1. 填写好“调用前输入”中列出的寄存器;
  2. 执行中断调用 int 0x15。
  3. 在CF位为0的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

在这里插入图片描述

利用BIOS中断0x15子功能0xe801获取内存

最大只能识别4GB内存。
检测到的内存分别放到两组寄存器中。
低于15MB的内存以1KB为单位大小来记录,单位数量在寄存器AX和CX中记录。实际内存容量=AX1024。
16MB~4GB是以64KB为单位大小来记录,单位数量在寄存器BX和DX中记录。实际内存容量=BX
64*1024。

子功能0xE801的调用方法:

  1. 将AX寄存器写入0xE801。
  2. 执行中断调用int 0x15。
  3. 在CF位为0的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

在这里插入图片描述

利用BIOS中断0x15子功能0x88获取内存

只能识别最大64MB的内存。即使内存容量大于64MB,也只会显示63MB。此中断只会显示1MB之上的内存,不包括这1MB。

0x15子功能0x88的调用方法:

  1. 将AX寄存器写入0x88。
  2. 执行中断调用int 0x15。
  3. 在CF位为0的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

在这里插入图片描述

实战内存容量检测

内存容量检测(实验)

启用内存分页机制,畅游虚拟空间

内存为什么要分页

CPU加载内存段的过程:
段描述符表描述了对应段的具体信息。CPU允许在描述符表中已注册的段不在内存中存在。当段不存在时,CPU会抛出异常引发中断,中断将相应的段从外存(如硬盘)中载入到内存,再将标志位置1(即段存在),再让CPU重新检查。

在这里插入图片描述

内存段移出到外存上:

当内存不够用时,就可以将使用频率低的段换出到硬盘,等用到的时候再从硬盘中载入到内存。这样就可以腾空一直占用内存却不经常使用是进程的段了。(CPU访问内存是用段基址定位的,如果段在内存中,就会一直占用一部分内存,但是如果它被移到硬盘,就不占内存了,而该段中的进程的地址是相对的,只要地址的相对位置不变,就不会影响执行。内存中的数据是二进制,段被换出到硬盘上以二进制形式存储,数据内容都是一样的,只是存储介质不同而已,无非就是一段二进制数据在内存和外存之间拷贝来拷贝去而已。)

段描述符A位由CPU置1,但清0工作是由操作系统完成的,操作系统每发现该位为1就将该位清零,这样就可以统计该段的使用频率。当物理内存不足时,可以将使用频率低的段换出到硬盘,以腾出内存空间给新的进程。当段被换出到硬盘后,操作系统将该段描述符的P位置置0。下次执行时,如果访问这个段就回到了上述CPU加载内存段的过程。

不足:
虽然能解决内存不足的问题,但是线性地址连续而物理地址不连续,这样的话就会执行的很慢。因此需要将线性地址映射到任意物理地址。也就是分页机制所做的事。

一级页表

没有分页机制的时候,CPU默认线性地址=物理地址,线性地址就是“段基址:段内偏移地址”。打开分页机制之后,段部件输出的线性地址不等于物理地址,我们称之为虚拟地址(线性地址)。CPU要想拿到物理地址需要在页表中查找。

在这里插入图片描述
在这里插入图片描述

分页机制原理:

线性地址就是“段基址:段内偏移地址”,为了方便寻址提高效率,线性地址是连续的。在分页机制之前,线性地址等于物理地址,但是这样的话就只能让物理地址也连续。但是由于物理内存不够,需要将段移来移去,不能保证物理地址连续。为了让线性地址能映射到任意物理地址,添加了分页机制。其实就是将线性地址与任意物理内存地址关联起来。这个时候线性地址不等于物理地址,所以也叫虚拟地址。

4GB的线性地址空间先映射到4GB的虚拟地址空间,在这里分页机制将大小不同的段拆分成大小相同的以页为单位的小块内存,操作系统为这些虚拟页分配真实的物理内存页,它查找物理内存中可用的页,然后在页表中登记这些物理页地址,这样就完成了虚拟页到物理页的映射,每个进程都以为自己独享4GB地址空间

在这里插入图片描述

分页机制的本质就是将大小不同的大内存段拆分成大小相等的小内存块。
内存块数 * 内存块大小=4GB。
页表所占内存=页大小 * 内存块数。
(要使得页表所占内存尽可能小且能包含4GB(32位)的地址)

CPU中采用的页大小为4KB,4GB地址空间被划分成4GB/4KB=1M个页。
在这里插入图片描述

一级页表模型:

一级页表

用线性地址找到页表中对应的页表项:
将页表的物理地址加载到寄存器cr3中,页表中页表项的地址就是物理地址。用线性地址的高20位作为页表项的索引。
在这里插入图片描述
地址转换:
在这里插入图片描述
用线性地址的高20位在页表中索引页表项,用线性地址的低12位与页表项中的物理地址相加,所求的和便是最终线性地址对应的物理地址。
因为页个数有20位,页大小为12位。那么索引范围就是20位,就用高20位表示,索引到了页的基地址,剩下的12位则用来填4KB大小的内存地址,在这个基地址下可以放12位的地址个数。也可以看作是“页基址(高20):页内偏移地址(低12)”
在这里插入图片描述

二级页表

为什么需要二级页表的原因:
一级页表占用空间大,表示的内存少。页表项需要提前建好。

在这里插入图片描述

标准页尺寸是4KB,4GB线性地址空间最多有1M个标准页。一级页表将1M个标准页放置在一张页表中,二级页表将1M个标准页平均放置在1K个页表中。二级页表使用页目录表存储页表,存储在页目录表中的页表的物理地址叫页目录项(PDE),4字节。页目录表大小=1K*4B=4KB。

在这里插入图片描述

在这里插入图片描述

二级页表转换:
页目录表-页目录项(页表地址)-页表-页表项(物理地址)
2 ^ 10 * 2 ^ 10 * 2 ^12
第31-22位定位页表,第21-12位定位物理页,第11-0位用于页内偏移量。

在这里插入图片描述
在这里插入图片描述

页表目录和页表项:

在这里插入图片描述
在这里插入图片描述

启动分页机制:

在这里插入图片描述

寄存器cr3用于存储页物理地址,又称其为页目录基址寄存器(PDBR)

在这里插入图片描述
启动分页机制的开关是将控制寄存器cr0的PG位置1。

规划页表之操作系统与用户进程的关系

当用户进程需要访问硬件相关的资源时,需要向操作系统申请,由操作系统去做,之后将结果返回给用户进程。进程可以有无限个,但操作系统只有一个,所以操作系统必须“共享”给所有用户进程。
用户进程相当于是一个半成品,还有部分功能需要操作系统,配合上操作系统才能实现一个完整的程序。

在这里插入图片描述

页表的设计是根据内存分布情况来决定的。在用户进程4GB虚拟地址空间的高3GB以上的部分划分给操作系统,0~3GB是用户进程自己的虚拟空间。为了实现共享操作系统,让所有用户进程3GB ~ 4GB的虚拟地址空间指向同一个操作系统,也就是所有进程的虚拟地址3GB ~ 4GB本质上都是指向的同一片物理页地址,这片物理页上是操作系统的实体代码。(每个进程都有4GB虚拟地址)

启用分页机制

启用分页机制(实验)

用虚拟地址访问页表

进入分页机制后,访问任何物理地址都需要通过虚拟地址进行。

页表是一种动态的数据结构,可以往里面添加页表项(申请内存),或者对某个页表项清零(释放内存)。

用虚拟地址访问页表自身:

  1. 让虚拟地址直接与物理地址一一对应。
  2. 让虚拟地址与物理地址乱序映射。

开启分页之后,我们可以使用 info tab 命令查看虚拟地址与物理地址的映射。cr3寄存器显示的就是页目录表的物理地址。
在这里插入图片描述

快表TLB简介

在这里插入图片描述

加载内核

用C语言写内核

汇编语言和机器指令几乎是一对一的,即一名汇编代码只对应一句具体的机器码,不会有更多对应的选择,所以可以认为汇编指令就是机器指令。C语言的编译过程是先将C语言代码转换成汇编代码,然后再将汇编代码转换成机器指令。所以用C语言写出来的程序,最终可以转换成对应的一句或多句汇编指令。

生成C语言程序的过程:
先将源程序编译成目标文件,再将目标文件链接成二进制可执行文件。
gcc -c -o file.o file.c

在这里插入图片描述
经过gcc编译后的目标文件是待重定位文件,文件中的符号还没有安排地址,需要等和其他文件一起“组成”可执行文件时再重新定位。

在这里插入图片描述

链接:

ld main.o -Ttext 0xc0001500 -e main -o kernel.bin

-Ttext 指定起始虚拟地址为0xc0001500
-o 指定输出的文件名
-e指定程序的起始地址,其参数可以是数字形式的地址,也可以是符号名,指定程序是从哪里开始的。也就是提供程序的入口。
由于程序内的地址是在链接阶段编排的,所以在链接阶段必须明确入口地址才行,于是链接器规定,默认只把名为_start的函数作为程序的入口地址,即默认的entry symbol是_start,除非另行指定。

二进制程序的运行方法

任何应用程序都需要被载入到内存后才能运行,这是CPU等其他硬件的运行机制决定的,不过它们通常位于磁盘等外存设备中,在使用时,需要从外存中将其调入到内存后才行。

加载用户程序就是通过操作系统去调用它。在此之前,我们都是把应用程序放在固定位置方便寻找,但是这样不够灵活。由于每个程序是单独存在的,所以程序的入口地址信息需要与程序绑定,最简单的办法就是在程序文件中专门腾出个空间来写入这些程序的入口地址,主调程序在该程序文件的相应空间中将程序的入口信息读出来,将其加载到相应的入口地址,跳转过去就行了。

所以就有了文件头(应该就是类似于头文件吧)。文件头用来描述程序的布局等信息,它属于信息的信息,也就是元数据。将这种具有程序头格式的程序文件从外存读入到内存后,从该程序文件的程序头读出入口地址,需要直接跳进入口地址执行,跨过程序头才行。

在这里插入图片描述

elf格式的二进制文件

ELF是指可执行链接格式。在ELF规范中,把符合ELF格式协议的文件统称为“目标文件”或ELF文件。
在这里插入图片描述

段和节是程序中最重要的部分。段是由节来组成的,多个节经过链接之后就被合并成一个段来。段和节的信息也是用header来描述的,程序头是program header,节头是section header。程序中段的大小和数量是不固定的,节的大小和数量也不固定,因此使用程序头表和节头表来描述它们,这两个表汇总了程序头和节头,表中元素是头信息。

在表中,每个成员都统称为条目,一个条目代表一个段或一个节的头描述信息。对于程序头表,它本质上就是用来描述段的。

需要在一个固定的位置,用一个固定大小的数据结构来描述程序头表和节头表的大小及位置,这个数据结构便是ELF header,它位于文件最开始的部分,并具有固定大小。

EFL文件是个用来描述各种“头”的“头”,程序头表和节头表中的元素也是程序头和节头。elf文件格式的核心思想就是头中嵌头,是种层次化结构的格式。

ELF文件分为文件头和文件体两部分。先用个ELF header从“全局上”给出程序文件的组织结构,概要出程序中其他头表的位置大小等信息,如程序头表的大小及位置、节头表的大小及位置。然后,各个段和节的位置、大小等信息再分别从“具体的”程序头表和节头表中予以说明。

ELF文件格式的作用体现在两方面,一是链接阶段,另一方面是运行阶段。无论是在待重定位文件还是可执行文件中,文件最开头的部分必须是 ELF header。接着是程序头表,这对可执行文件是必须存在的,而对待重定位文件是可选的。其他成员位置要取决于各头表中的说明。
在这里插入图片描述
在这里插入图片描述

ELF header 结构:
在这里插入图片描述

e_ident[16]是16字节大小的数组,用来表示elf字节等信息,开头的4个字节是固定不变的,是elf文件的魔数,它们分别是0x7f,以及字符串ELF的ASCII码:0x45,0x4c,0x46。

e_type占2字节,是用来指定elf目标文件的类型。

e_machine占2字节,用来描述elf目标文件的体系结构类型,也就是说要在哪种硬件平台上才能运行。

在这里插入图片描述

程序头表中的条目的数据结构:
在这里插入图片描述
在这里插入图片描述

elf文件实例

在这里插入图片描述
(划细线属于elf header范围,粗下划线属于program header 范围)

在这里插入图片描述

在这里插入图片描述

将内核载入内存

将内核载入内存(实验)

特权级深入浅出

特权级的那点事

计算机可以分为两部分,访问者和受访者。访问者是动态的,具有能动性,它主动去访问各种资源。受访者是静态的,它是被访问的资源,只能等着访问者访问。访问者的特权级可以变,受访者的特权不能变。

建立特权机制是为了通过特权来检查合法性,检查访问者的特权级和受访者的特权级是否匹配。

特权级按照权力从大到小分为0、1、2、3级,0级特权能力最大,3级特权能力最小。0级特权是我们操作系统内核所在的特权级。

在这里插入图片描述

TSS简介

TTS是任务状态段,它是处理器在硬件上原生支持多任务的一种实现方式。TTS是一种数据结构,它用于存储任务的环境。
TTS是每个任务都有的结构,它用于一个任务的标识,相当于身份证,程序拥有此结构才能运行,这是处理器硬件上用于任务管理的系统结构,处理器能够识别其中每个字段。

在这里插入图片描述

在没有操作系统的情况下,可以认为进程就是任务,任务就是一段在处理器上运行的程序。有了操作系统之后,程序分为用户部分和内核部分。一个任务按特权级来划分的话,实质上是被分成了3特权级的用户程序和0特权级的内核程序,这两部分加在一起才是能让处理器完整运行的程序,也就是说完整的任务要经历这两种特权的变换。

每个任务的每个特权级下只能有一个栈,不存在一个任务的某个特权级下存在多个同特权级栈的情况。一个任务最多有4个栈。一个任务可以拥有的栈的数量取决于当前特权级是否还有进一步提高的可能,即取决于它最低的特权级别。

一个TSS中只有3个栈:ss0和esp0,ss1和esp1,ss2和esp2,它们分别代表0级栈的段选择子和偏移量、1级栈的段选择子和偏移量、2级栈的段选择子和偏移量。因为除了调用返回外,处理器只能由低特权级向高特权级转移,TSS中所记录的栈是转移后的高特权级,只用于向更高特权级转移时提供相应特权的栈地址。当由高特权返回低特权级的情况,处理器是不需要在TSS中去寻找低特权级目标栈的。当处理器由低向高特权级转移时,它自动地把当时低特权级的栈地址压入了转移后的高特权级所在的栈中,所以,当用返回指令如retf或iret从高特权级向低特权级返回时,处理器可以从当前使用的高特权级的栈中获取低特权级的栈段选择子及偏移量。由高特权级返回低特权级的过程称为“向外层转移”。

CPL和DPL入门

访问者就是指令,指令的访问请求看他有没有特权级,特权级就在代码段寄存器CS中选择子的RPL位的值。在任意时刻,当前特权级CPL保存在CS选择子中的RPL部分。代码是执行者,它表示访问的请求者,所以CPL只存放在代码段寄存器CS中低2位的RPL中。
CPL是当前CPU所处的特权级,也就是当前特权级。


在这里插入图片描述

DPL是描述符特权级,是段描述符所代表的内存区域的“门槛”权限。访问者任何时候都不允许访问比自己特权更高的资源。对于受访者是数据段来说,只有访问者的权限大于等于该DPL表示的最低权限才能够继续访问。对于受访者是代码段来说,只有访问者的权限等于该DPL表示的最低权限才能够继续访问,即只能平级访问,任何权限大于或小于它的访问都将被CPU拒之门外。

唯一一种处理器会从高特权级降到低特权级运行的情况:处理器从中断处理程序中返回到用户态的时候。中断处理都是在0特权级下进行的。

**一致性代码段:**转移后的特权级与转移前的特权级一致。
在这里插入图片描述

门、调用门与RPL序

门结构用来记录一段程序起始地址的描述符。
门描述符用来描述一段程序,同段描述符类似,都是8字节大小的数据结构。
门是用来实现从低特权级的代码段转向高特权级的代码段。

门的“门槛”的访问者的下限,访问者的特权级再低也不能比门描述符的特权级DPL低。否则访问者连门都进不去。门描述符相当于数据段描述符一样,只允许比自己特权级高或相同特权级的程序访问。
门的“门框”是访问者特权级的上限,访问者的特权级再高也不能比门描述符中目标程序所在代码段的DPL高,否则就变成特权级由高转低了。
门结构存在的目的就是为了让处理器提升特权级,这样处理器才能够做一些低 特权级下无法完成的工作。

在这里插入图片描述
在这里插入图片描述

调用门执行流程:

在这里插入图片描述

调用门的过程保护

调用门的过程:从特权级3到特权级0
用户进程为调用门提供两个参数,将这两个参数压入特权级3栈中->确定新特权级使用的栈->检查新栈段选择子中的描述符的DPL和TYPE->切换到新栈,将旧栈段选择子和指针临时保存->使用新栈后压入旧栈段选择子和指针->压入之前的两个参数->压入当前代码段的CS和EIP->把门描述符中的选择子加载到代码段CS中,偏移量装载到EIP中。
在这里插入图片描述

调用门返回过程:

在这里插入图片描述

在这里插入图片描述
(就是在从低到高时把DS的权限提高了,但是返回变成从高到低时又忘记改回来了,这样DS就能访问高特权的数据了,越权。于是往里面填0,第0个段描述符是不可用的,这样处理器就可以引发异常)
在这里插入图片描述
在这里插入图片描述

RPL的前世今生

当用户程序需要访问比他特权级高的数据时,他就需要调用门或者其他使它可以访问到这个数据,但是这个数据其实不是由它直接访问的,因为它没有这个权限,它是让特权级更高的内核来帮忙访问然后写入特定缓存中。
当处理器需要内核数据时,它要变成0特权级,而此时它就可以为所欲为,缺乏安全保证。所以必须弄清楚真正的请求者是谁,内核程序只是代替用户程序来拿数据的。
在这里插入图片描述

RPL是请求特权级,它代表真正请求者的特权级,代表真正资源需求者的CPL。RPL的引入是为了避免低特权级的程序访问高特权级的资源。
在这里插入图片描述
在这里插入图片描述

使用arpl指令来修改选择子中的RPL。
在这里插入图片描述

在这里插入图片描述

CPL是当前进程的权限级别(Current Privilege Level),是当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位。
RPL是进程对段访问的请求权限(Request Privilege Level),是对于段选择子而言的,每个段选择子有自己的RPL。RPL可能会削弱CPL的作用,例如当前CPL=0的进程要访问一个数据段,它把段选择符中的RPL设为3,这样虽然它对该段仍然只有特权为3的访问权限。
DPL存储在段描述符中,规定访问该段的权限级别(Descriptor Privilege Level),每个段的DPL固定。当进程访问一个段时,需要进程特权级检查,一般要求DPL >= max {CPL, RPL}。
也就是说,CPL是当前程序的权限,RPL是对段访问的权限(请求者的权限),DPL是访问这个段需要的权限(访问者权限)。在访问段(DPL)时,虽然内核(CPL)可以访问,但是它其实是替用户程序(RPL)访问的,但用户程序是不能访问的
在这里插入图片描述

IO特权级

除了代码访问和数据访问有特权级,指令和IO口读写也有特权级。有些指令只有在0特权级下才能使用,如hlt,lgdt,lidt,ltr,popf等。IO读写特权由标志寄存器eflags中的IOPL位的IO位图决定,IO相关的指令只有在当前特权级(CPL)大于等于IOPL时才能执行。
在这里插入图片描述

**eflags寄存器:**每个任务都有自己的eflags,其中的IOPL表示了当前任务要想执行全部IO指令的最低特权级。

在这里插入图片描述

IOPL设置:

在这里插入图片描述
驱动程序:

在这里插入图片描述
IO位图: IOPL是所有IO端口的开关,如果开关被关上,则可以通过IO位图来设置部分端口的访问权限

位图就是一个用bit映射到某个实际的对象。位图这种结构的操作单位就是bit,所以位图就是一串二进制01数字,对位图的操作也就是读写相应的位,处理器中对内存的访问是以字节为单位的,不能直接操作位,所以要先将该位所在的字节读到内存,若是想将该位置1,可用1对该位进行或操作,若想将该位清0可以用0对该位进行与操作。

位图中的每一bit代表一个端口。0表示可以访问,1表示禁止访问。IO位图只有在CPL>IOPL才有效

在这里插入图片描述

TSS如果有位图将位于TSS顶端,如果偏移地址不在此范围则表示没有IO位图。

在这里插入图片描述

**IO位图结尾的0xff:**0xff就是说这几个端口都不能访问。

在这里插入图片描述

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

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

相关文章

医院PACS系统源码,PACS源码,带3D重建PACS系统源码

PACS系统源码,带3D重建PACS源码 专门针对医院工作流程设计的,完全符合医院需要,配置灵活的放射科信息化解决方案。采用标准接口协议,实现预约登记、报告诊断、图像浏览和处理、信息统计等功能。 文末获取联系! 功能介…

基于广义benders分解法的综合能源系统优化规划(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

用友U8 cloud,信创云ERP的数智先锋

编辑:阿冒设计:沐由从来未曾有过一个春天,能够像当下这般被如此由衷地期待。经历了漫长的1000多个日日夜夜之后,我们的工作与生活终于回到正轨。自2023年以来,中国市场迎来“开门红”,消费市场加速回暖&…

分类算法性能度量指标

1.简介 为了了解模型的泛化能力,我们需要用某个指标来衡量,这就是性能度量的意义。常用的评估指标有:混淆矩阵(Confuse Matrix)、准确率(Accuracy)、精准率(Precision)和召回率(Recall)、F1-Score、ROC曲线(Receiver Operating Characteristi…

离散数学_九章:关系(1)

关系9.1关系及其性质 1、二元关系 2、集合A上的关系 3、n元素集合 有多少个关系? 4、关系的性质 1. 自反 2. 对称 3. 反对称 4. 传递 5、关系的组合 关系的合成 关系的幂 9.1关系及其性质 1、二元关系 设A和B是集合,一个从 A 到 B 的二元关系是…

Pytorch基础 - 8. scatter() / scatter_() 函数

目录 1. scatter() 定义和参数说明 2. 示例和详细解释 3. scatter() 常见用途 1. scatter() 定义和参数说明 scatter() 或 scatter_() 常用来返回根据index映射关系映射后的新的tensor。其中,scatter() 不会直接修改原来的 Tensor,而 scatter_() 直接…

元宇宙:虚拟仿真技术的全面提升

在当今数字化的世界中,我们经常听到虚拟现实、增强现实、混合现实等技术的名词,这些技术的应用越来越成熟。其中,虚拟仿真技术是一种通过计算机技术来模拟实际场景和对象的过程,它为我们提供了更多的可能性。而最近备受瞩目的元宇…

减震无人船或波浪自适应无人船

最近我的朋友夏先生介绍了一款他们自己正在研发的一款无人减震船,见下图,与以前无人船相比,它增加了悬挂减震系统(图中红框内)。 现有无人船大多属于中小型船舶,没有完善的减震减摇系统,减震减摇…

MIPI 打怪升级之DBI篇

目录1 Overview2 Display Architectures2.1 Type 1 Display Architecture Block Diagram2.2 Type 2 Display Architecture Block Diagram2.3 Type 3 Display Architecture Block Diagram2.4 Type 4 Display Architecture Block Diagram3 Interface Signal Description3.1 Type …

202306读书笔记|《与诗书在一起》——质而实绮,癯而实腴

《与诗书在一起》作者叶嘉莹,不错的一本书,大多只看了诗,部分读着比较有感觉的看了注释。 很喜欢的节选如下: 苏轼说陶渊明的诗“质而实绮,癯而实腴”,就是看起来它很简单质朴,内里实在是很美丽很丰富。 …

VS2010编译libcurl库并简单使用(c语言)

libcurl是什么? libcurl主要功能就是用不同的协议连接和沟通不同的服务器~也就是相当封装了的sockPHP 支持libcurl(允许你用不同的协议连接和沟通不同的服务器)。 libcurl当前支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议…

Spring 之依赖注入底层原理

Spring 框架作为 Java 开发中最流行的框架之一,其核心特性之一就是依赖注入(Dependency Injection,DI)。在Spring中,依赖注入是通过 IOC 容器(Inversion of Control,控制反转)来实现…

助力研发效能变革,第七届Techo TVP 开发者峰会圆满落下帷幕

引言 在互联网数字企业结束“野蛮扩张”、追求高质量增长的今天,研发效能已然成为企业关注的核心命题。伴随着云原生概念在软件领域的落地生根,云原生正驱动软件应用设计、实现、部署及运维方式的巨变,为研发效能治理带来了新的挑战与机遇&am…

2022国赛31:虚拟化-------安装docker

大赛试题内容: 八、虚拟化(20) 在Windows3安装docker,导入NanoServer镜像。软件包和镜像存放在物理机D:\soft\DockerWindows。创建名称为web的容器,映射虚拟机的80端口到容器的80端口,容器启动后运行cmd命令,保持容器处于运行状态。解答过程: windows docker 安装 1.添…

知识图谱嵌入方法-transE

目录 一、知识图谱嵌入 二、transE算法 三、缺点 一、知识图谱嵌入 知识图谱(Knowledge Graph,KG) 是大规模语义网络知识库,利用三元组(实体,关系,实体)来描述具体的知识,其具有语义丰富、结…

vue-element-admin 动态菜单改造

vue-element-admin 动态菜单改造 vue-element-admin 是一款优秀后台前端解决方案,它基于 vue 和 element-ui实现。开源后台管理系统解决方案项目 Boot-admin的前端模块就是基于vue-element-admin开发而来。 作为一款纯前端的后台界面解决方案,vue-elem…

剑指 Offer 51. 数组中的逆序对

剑指 Offer 51. 数组中的逆序对 难度:hard\color{red}{hard}hard 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 示例 1: 输入: [7…

怎么设计秒杀系统?

秒杀系统需要考虑哪些要素? 要能支持高并发用户体验要好,不要返回异常信息对系统要友好(针对秒杀可以做业务上的隔离,单独把秒杀系统部署到独立的集群服务器上;可动态配置业务参数,比如商品金额&#xff0…

电磁兼容(EMC)的标准与测试内容

在国际范围上,电磁兼容标准的制定已经有了70多年的发展历程,最早为了保护无线电通信和广播,国际无线电干扰特别委员会(CISPR)对各种用电设备和系统提出了相关的电磁干扰发射限值和测量方法。到了20世纪60~7…

机器学习:基于朴素贝叶斯(Naive Bayes)的分类预测

目录 一、简介和环境准备 简介: 环境: 二、实战演练 2.1使用葡萄(Wine)数据集,进行贝叶斯分类 1.数据导入 2.模型训练 3.模型预测 2.2模拟离散数据集–贝叶斯分类 1.数据导入、分析 2.模型训练、预测 三、原…