软件和硬件数据交互接口的的演进

2023-11-06

编者按AMD Kria SOM及KV260视觉入门套件介绍 - 电子发烧友在线研讨会

软件和硬件,既相互依存又需要某种程度上的相互独立。通过软件和硬件之间的接口把两者连接在一起。软硬件接口,有很多含义:比如指令集是CPU软件和硬件之间的接口;比如一些硬件模块(包括IO接口模块、GPU、各种加速引擎等)暴露出来的可读写寄存器,则为控制接口;再比如,CPU和GPU或其他硬件模块之间通过DMA进行数据交互的(软硬件间的)数据传输接口。 软硬件接口,是个非常庞大的命题。本文是《软硬件融合》图书内容的节选,聚焦在软件和硬件之间的数据交互接口。

软件和硬件之间数据交互接口

我们在计算机的基础课程里一般都学过IO交互的四种模式:寄存器模式、中断模式、DMA模式和通道模式。随着计算机技术的发展,除了IO设备,还有很多独立的硬件组件通过各种类型总线跟CPU连接在一起。接口已经不仅仅是用于IO数据传输场景,也用于软件(运行于CPU的程序)和其他硬件之间的数据交互场景。 注:本文用“软硬件接口”特指软件和硬件之间数据交互的接口。

1 软硬件接口定义

传统的非硬件缓存一致性总线,是需要软件驱动显式的控制设备来进行数据交互的。通过梳理软硬件接口的演进,逐步给出软硬件接口的定义。 a. 软硬件接口演进

(a) CPU轮询                   (b) CPU中断                   (c) DMA方式

(d) 共享队列                

(e) 用户态轮询                 

(f) 多队列 图1 软硬件接口的演进 软硬件接口是在IO接口基础上的扩展,如图1,我们结合IO交互的四种模式,重新梳理一下软硬件接口的演进:

第一阶段,使用软件轮询硬件状态。如图1(a),最开始是通过软件轮询,这时候软件和硬件的交互非常简单。发送的时候,软件会定期的去查询硬件的状态,当发送缓冲为空的时候,就把数据写入到硬件的缓存寄存器;接收的时候,软件会定期的查询硬件的状态,当接收缓冲区有数据的时候,就把数据读取到软件。

第二阶段,使用中断模式。如图1(b),随着CPU的性能快速提升,统计发现,轮询的失败次数很高,大量的CPU时间被浪费在硬件状态查询而不是数据传输,因此引入中断模式。只有当发送缓冲存在空闲区域可以让软件存放一定量待发送数据的时候,或者接收缓冲已经有一定量数据待软件接收的时候,硬件会发起中断,CPU收到中断后进入中断服务程序,在中断服务程序里处理数据的发送和接收。

第三阶段,引入DMA。如图1(c),前面的两种情况下,都需要CPU来完成数据的传输,依然会有大量的CPU消耗。因此引入了专用的数据搬运模块DMA来完成CPU和硬件之间的数据传输,某种程度上,DMA可以看做是用于代替CPU进行数据搬运的加速器。发送的时候,当数据在CPU内存准备好,CPU告诉DMA源地址和数据的大小,DMA收到这些信息后主动把数据从CPU内存搬到硬件内部。同样的,接收的时候,CPU开辟好一片内存空间并告知DMA目标地址和空间的长度,DMA负责把硬件内部的数据搬运到CPU内存。

第四阶段,专门的共享队列。如图1(d),引入了DMA之后,如果只有一片空间用于软件和硬件之间的数据交换,则软件和硬件之间的数据交换则是同步的。例如在接收的时候,当DMA把数据搬运到CPU内存之后,CPU需要马上进行处理并释放内存,CPU处理的时候DMA则只能停止工作。后来引入了乒乓缓冲的机制,当一个内存缓冲区用于DMA传输数据的时候,另一个缓冲区的数据由CPU进行处理,实现DMA传输和CPU处理的并行。更进一步的,演变成更多缓冲区组成的循环缓冲队列。这样,CPU的数据处理和DMA的数据传输则完全异步的完成,并且CPU对数据的处理以及DMA对数据的搬运都可以批量操作完成后,再同步状态信息给对方。

第五阶段,用户态的软件轮询共享队列驱动。如图1(e),进一步的,随着带宽和内存的增加,导致数据频繁的在用户态应用程序、内核的堆栈、驱动以及硬件之间交互,并且缓冲区也越来越大,这些都不可避免的增加系统消耗,并且带来更多的延迟;而且,数据交互频繁,导致的中断的开销也是非常庞大的。因此,通过用户态的PMD(Polling Mode Driver,轮询模式驱动)可以高效的在硬件和用户态的应用程序直接传递数据,不需要中断,完全绕开内核,以此来提升性能和降低延迟。

第六阶段,支持多队列。如图1(f),随着硬件设计规模扩大,硬件资源越来越多,在单个设备里,可以通过多队列的支持,来提高并行性。驱动也需要加入对多队列的支持,这样我们甚至可以为每个应用程序配置专用的队列或队列组,通过多队列的并行性来提升性能和应用数据的安全性。

说明:本小节所讲的内容,主要是基于传统的非缓存一致性总线的数据交互演进。随着跨芯片的缓存数据一致性总线开始流行,通过硬件完成数据交互,在提升性能的同时,也简化了软件设计。 b. 软硬件接口的组成部分 粗略的说,软硬件接口是由驱动(Driver)和设备(Device)组成,驱动和设备的交互也即软件和硬件的交互。更确切一些的说,软硬件接口包括交互的驱动软件、硬件设备的接口部分逻辑,也包括内存中的共享队列,还包括传输控制和数据信息的总线。

图2软硬件接口硬件架构示意模型 如图2,是软硬件接口硬件架构的示意模型。软硬件接口的组件详细介绍如下:

驱动软件。驱动是提供一定的接口API,让上层的软件能够更加方便的与硬件交互。驱动负责硬件设备控制面的配置、运行控制以及设备数据面的数据传输控制等。驱动屏蔽硬件的接口细节,对上层软件提供标准的API函数接口。驱动屏蔽硬件细节,提供标准API给上层软件,在单机系统是非常有价值的。通过不同版本的驱动,既可以屏蔽硬件细节,又可以跟不同的操作系统平台兼容。在云计算场景,要求要更严格一些,云场景期望是完全标准的硬件接口。驱动是代表软件与硬件交互的接口,但依然是软件的一部分,在云计算虚拟机驱动也会迁移到新的环境,这就要求新的运行环境和原始环境一致。也就是说,在IO直通模式下,需要双方的硬件接口本身就是一致的。

设备硬件接口子模块,包括DMA和内部缓冲。高速的设备一般都有专用的DMA,专门负责数据搬运。驱动会通知DMA共享队列状态信息,然后DMA会读取内存中的共享队列描述符,并根据描述符信息负责在CPU内存和内部缓冲之间搬运数据。

共享队列。特定的跟硬件DMA格式兼容的共享队列数据结构,软件和硬件通过共享队列交互数据。每个共享队列包括队列的头和尾指针、组成队列的各个描述符项以及每个描述符项所指向的实际的数据块。共享队列位于软件侧的CPU内存里,由软件驱动负责管理。

传输的总线:软硬件交互可以说是上层功能,需要底层接口总线的承载。例如,在片内通常是通过AXI-Lite总线来实现软件对硬件的寄存器读写控制,而数据总线则是通过AXI实现硬件DMA对软件的CPU内存的读写访问。芯片间的总线常见的主要是PCIe,通过PCIe的TLP包来承载上层的各种类型的读写访问。

2 生产者消费者模型

生产者消费者问题(Producer-Consumer Problem)是多进程同步问题的经典案例之一,描述了共享固定大小缓冲区的两个进程,即所谓的“生产者”和“消费者”,在实际运行时如何处理交互的问题。 如图3所示,生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者不会在缓冲区中空时消耗数据。

图3 经典生产者消费者模型 解决问题的基本办法是:让生产者在缓冲区满时休眠,等到消费者消耗缓冲区中的数据,从而缓冲区有了空闲区域的时候,生产者才能被唤醒,开始继续往缓冲区添加数据;同样,也需要让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者继续消耗数据。 a. 进程间通信 一个生产者进程,一个消费者进程,生产者进程通过共享缓冲传递数据给消费者进程。如果程序员不够小心,没有考虑多进程间相互影响的话,很可能写出下面这段会导致“死锁”的代码。

// 该算法使用了两个系统库函数:sleep 和 wakeup。
// 调用 sleep的进程会被阻断,直到有另一个进程用wakeup唤醒之。
// 代码中的itemCount用于记录缓冲区中的数据项数。
int itemCount = 0;


procedure producer() {
    while (true) {
        item = produceItem();
        if (itemCount == BUFFER_SIZE) {
            sleep();
        }
        putItemIntoBuffer(item);
        itemCount = itemCount + 1;
        if (itemCount == 1) {
            wakeup(consumer);
        }
    }
}


procedure consumer() {
    while (true) {
        if (itemCount == 0) {
            sleep();
        }
        item = removeItemFromBuffer();
        itemCount = itemCount - 1;
        if (itemCount == BUFFER_SIZE - 1) {
            wakeup(producer);
        }
        consumeItem(item);
    }
}

上面代码中的问题在于它可能导致竞争条件,进而引发死锁。考虑下面的情形:

消费者进程把最后一个itemCount的内容读出来(注意它现在是零),消费者进程返回到while的起始处,现在进入if块。

就在调用sleep之前,OS调度,决定将CPU时间片让给生产者进程,于是消费者进程在执行sleep之前就被中断了,生产者进程开始执行。

生产者进程生产出一项数据后将其放入缓冲区,然后在itemCount上加 1;由于缓冲区在上一步加1之前为空,生产者尝试唤醒消费者。

遗憾的是,消费者并没有在休眠,唤醒指令不起作用。当消费者恢复执行的时候,执行 sleep,一觉不醒(出现这种情况的原因在于,消费者只能被生产者在itemCount为1的情况下唤醒)。

生产者不停地循环执行,直到缓冲区满,随后进入休眠。

由于两个进程都进入了永远的休眠,死锁情况出现了。因此,该算法是不完善的。我们可以通过引入信号量(Semaphore)的方式来完善这个算法。信号量能够实现对某个特定资源的互斥访问。

// 该方法使用了两个信号灯,fillCount和emptyCount;
// fillCount用于记录缓冲区中存在的数据项数量;
// emptyCount用于记录缓冲区中空闲空间数量;


// 当有新数据项被放入缓冲区时,fillCount增加,emptyCount减少;
// 当有新数据项被取出缓冲区时,fillCount减少,emptyCount增加;


// 如果在生产者尝试减少emptyCount的时候发现其值为零,那么生产者就进入休眠。
// 等到有数据项被消耗,emptyCount增加的时候,生产者才被唤醒。
// 消费者的行为类似。


semaphore fillCount = 0;                                         // 生产的项目
semaphore emptyCount = BUFFER_SIZE;         // 剩余空间
procedure producer() {
    while (true) {
        item = produceItem();
        down(emptyCount);
            putItemIntoBuffer(item);
        up(fillCount);
    }
}


procedure consumer() {
    while (true) {
        down(fillCount);
            item = removeItemFromBuffer();
        up(emptyCount);
        consumeItem(item);
    }
}

b.分布式消息队列服务 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削峰等问题。消息(Message)是指在应用之间传送的数据,消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,有消息系统来确保信息的可靠传递,消息发布者只管把消息发布到MQ中而不管谁来取,消息使用者只管从MQ中取消息而不管谁发布的,这样发布者和使用者都不用知道对方的存在。 如图4,消息队列一般由三部分组成:

Producer:消息生产者,负责产生和发送消息到 Broker。

Broker:消息处理中心。负责消息存储、确认、重试等,一般其中会包含多个Queue。

Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理。

图4 消息队列模型 消息队列具有如下特性:

异步性。将耗时的同步操作,通过发送消息的方式,进行了异步化处理。减少了同步等待的时间。

耦合。消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节,只要定义好消息的格式就行。

分布式。通过对消费者的横向扩展,降低了消息队列阻塞的风险,以及单个消费者产生单点故障的可能性(当然消息队列本身也可以做成分布式集群)。

可靠性。消息队列一般会把接收到的消息存储到本地硬盘上(当消息被处理完之后,存储信息根据不同的消息队列实现,有可能将其删除),这样即使应用挂掉或者消息队列本身挂掉,消息也能够重新加载。

互联网场景使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。 c. 驱动和设备通信 NIC(Network Interface Adapter,网络接口卡)是典型的IO设备,网络数据包的传输有发送Tx和接收Rx两个方向。通过贡献的Tx Queue和Rx Queue来交互数据传输。我们以网络Tx的传输为例,介绍基于生产者消费者模型的驱动和设备数据交互。 如图5,给出了网络包处理Tx发送的基本原理示意图(Rx接收跟Tx发送类似,控制流程一致,数据方向相反)。可以看到,在Tx的时候,驱动是生产者,设备是消费者,他们通过内存中共享的环形队列传输数据。一般在环形队列中的是用于描述数据的描述符,通过指针指向实际的数据块。当上层应用通过驱动把数据写到环形队列以后,驱动会把环形队列相关的状态信息告知设备端。设备端接收到信息后DMA开始工作,首先读取环形队列中的相应描述符,然后通过描述符信息搬运实际的数据块到硬件内部。搬运完成后硬件通过中断告知驱动,然后驱动会释放此块缓冲。

图5 网络驱动和设备通信示意图

3 用户态轮询驱动:DPDK和SPDK

DPDK和SPDK是当前主流的开源高速接口框架,核心的技术是用户态的轮询驱动。DPDK/SPDK支持两个核心的设备类型:DPDK聚焦高性能网络处理,SPDK聚焦高性能存储处理。 a. DPDK介绍

DPDK(Data Plane Development Kit,数据平面开发套件)是在用户态中运行的一组软件库和驱动程序,可加速在CPU架构上运行的数据包处理工作负载。DPDK由英特尔大约在2010年创建,现在作为Linux基金会下的一个开源项目提供,在拓展通用CPU的应用方面发挥了重要作用。

(a) 基于Linux内核的包处理 (b) 基于DPDK的包处理

图6 基于DPDK的包处理 如图6(a),传统Linux网络驱动存在如下一些问题:

中断开销大,大量数据传输会频繁触发中断,中断开销系统无法承受;

数据包从内核缓冲区拷贝到用户缓冲区,带来系统调用和数据包复制的开销;

对于很多网络功能来说,TCP/IP协议并非数据转发必需;

操作系统调度带来的缓存替换也会对性能产生负面影响。

如图6(b),DPDK最核心的功能是提供了用户态的轮询模式驱动,为了加速网络IO,DPDK允许传入的网络数据包直通到用户空间而没有内存复制的开销,不需要用户空间和内核空间切换时的上下文处理。DPDK可在高吞吐量和低延迟敏感的场景加速特定的网络功能,如无线核心、无线访问、有线基础设施、路由器、负载均衡器、防火墙、视频流、VoIP等。DPDK所使用的优化技术主要有:

用户态驱动,减少内核态用户态切换开销,减少缓冲区拷贝;

轮询模式驱动(PMD, Polling Mode Driver),不需要中断,没有中断开销,并且对队列及数据及时处理,降低延迟;

固定处理器核,减少线程切换的开销,减少缓存失效,同时要考虑NUMA特性,确保内存和处理器核在同一个NUMA域中;

大页机制,减少TLB未命中几率;

非锁定的同步,避免等待;

内存对齐和缓存对齐,有利于内存到缓存的加载效率;

DDIO机制,从IO设备把数据直接送到L3缓存,而不是送到内存。

b. SPDK介绍 在数据中心中,固态存储介质正在逐渐替换机械HDD,NVMe在性能、功耗和机架密度方面具有明显的优势。因为固态存储吞吐量提升,存储软件需要花费更多的CPU资源;因为固态存储延迟性能的大幅提升,存储软件的处理延迟则开始凸显。总结来说,随着存储介质性能的进一步提升,存储软件栈的性能和效率越来越成为存储系统的瓶颈。 如图7,SPDK(Storage Performance Development Kit,存储性能开发套件)利用了很多DPDK的组件,在DPDK的基础上,加入了存储的相关组件。SPDK的核心技术依然是用户态的PMD。SPDK已经证明,使用一些处理器内核和一些NVMe驱动器进行存储,而无需额外的卸载硬件,可以轻松实现每秒数百万个IO。

图7 SPDK基于DPDK和一些新的组件 SPDK由许多组件组成,这些组件相互连接并共享用户态和轮询模式操作的通用功能。每个组件都是为了克服特定场景的性能瓶颈而开发的,并且,每个组件也可以集成到非SPDK架构中,从而使客户可以利用SPDK的技术来加速自己的软件应用。从底层到上层,SPDK的组件包括:

用户态PMD驱动:基于PCIe的NVMe驱动、NVMeoF驱动,以及英特尔QuickData驱动(QuickData为Intel志强处理器平台的IO加速引擎)。

后端块设备:Ceph RADOS块设备(Ceph为开源的分布式存储系统,RADOS为Ceph的分布式集群封装),Blobstore块设备(VM或数据库交互的虚拟设备),Linux AIO(异步IO)。

存储服务:块设备抽象层(bdev),Blobstore。

存储协议:iSCSI Target端,NVMeoF Target端,vhost-scsi Target端,vhost-blk Target端。

编辑:黄飞

转自https://www.elecfans.com/emb/jiekou/202210311915098.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

软件和硬件数据交互接口的的演进 的相关文章

  • SetWindowsHookEx 函数返回 NULL

    我正在研究 DLL 注入 但收到错误如下 挂接进程失败 87 参数不正确 目标进程和dll都是64位的 注入代码为 BOOL HookInjection TCHAR target TCHAR dll name https msdn micr
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • 没有 Unicode 字节顺序标记。无法切换到 Unicode

    我正在使用 XSD 编写 XML 验证器 下面是我所做的 但是当验证器到达该线时while list Read 它给了我错误 没有 Unicode 字节顺序标记 无法切换到 Unicode 有人可以帮我解决吗 public class Va
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • WebClient读取错误页面的内容

    我有一个加载页面内容的应用程序 我使用 WebClient 类 即使服务器返回 404 500 等错误 我也需要检索内容 我需要这样的东西 WebClient wc new WebClient string pageContent try
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • 在通过网络发送之前压缩位图

    我正在尝试通过网络发送位图屏幕截图 因此我需要在发送之前对其进行压缩 有一个库或方法可以做到这一点吗 当您将图像保存到流时 您have选择一种格式 几乎所有位图格式 bmp gif jpg png 都使用一种或多种压缩形式 因此 只需选择适
  • 导出到 CSV 时 Gridview 出现空行

    这个问题是由进一步讨论引发的这个问题 https stackoverflow com questions 6674555 export gridview data into csv file 6674589 noredirect 1 com
  • 指示泛型返回动态类型的对象

    这个问题是我原来问题的后续问题here https stackoverflow com questions 2541184 using a type object to create a generic 假设我有以下泛型类 简化 class
  • Microsoft.Graph - 如何从具有不同用户名的共享邮箱发送?

    我目前正在将使用 SMTP 的服务代码移植到 Office 365 通过 SMTP 我可以使用 发件人 字段在来自共享收件箱的邮件上设置不同的用户名 同时保留共享电子邮箱地址 这似乎无法通过 Office 365 运行 其工艺流程为 客户填
  • 在“using”语句中使用各种类型 (C#)

    自从C usingstatements只是try finally dispose 的语法糖 为什么它接受多个对象仅当它们属于同一类型时 我不明白 因为它们需要的只是 IDisposable 如果它们都实现 IDisposable 应该没问题
  • c# 如何生成锦标赛括号 HTML 表

    所以我已经被这个问题困扰了三个星期 但我一生都无法弄清楚 我想做的是使用表格获得这种输出 演示 http www esl world net masters season6 hanover sc2 playoffs rankings htt
  • 更改其他页面的主窗口内容

    在 WPF 应用程序的主窗口中 我有一个 Badged 元素 来自材料设计 这是我的代码
  • 如何不在类中实现接口的功能?

    面试时面试官问了我以下问题 但我不知道这个问题的答案是什么 请帮忙 如果我不想 我必须做什么 在我的类中实现一个函数 在接口中声明为 由我班实施 Edited 我正在使用 NET 和 C 如果有人可以提供 C 示例代码示例 那就太好了 Th
  • 如何将字符串转换为 Indian Money 格式?

    我正在尝试将字符串转换为印度货币格式 例如如果输入为 1234567 则输出应为 12 34 567 我编写了以下代码 但它没有给出预期的输出 CultureInfo hindi new CultureInfo hi IN string t
  • 如何查找哪个 Yocto 项目配方填充图像根文件系统上的特定文件

    我经常与 Yocto 项目合作 一个常见的挑战是确定文件为何 或来自什么配方 包含在 rootfs 中 这有望从构建系统的环境 日志和元数据中得出 理想情况下 一组命令将允许将文件链接回源 即配方 我通常的策略是对元数据执行搜索 例如gre
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • 将 bignum 类型结构转换为人类可读字符串的有效方法是什么?

    我有一点问题 为了增长我的 C 知识 我决定尝试实现一个基本的 bigint 库 bigint 结构的核心将是一个 32 位整数数组 选择它们是因为它们适合寄存器 这将允许我在数字之间进行操作 这些操作将在 64 位整数中溢出 这也将适合寄
  • 是否有任何不使用公共虚拟方法的正当理由? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 是否有任何不使用公共虚拟方法的正当理由 我在某处读到我们应该避免使用公共虚拟方法 但我想向专家确认这是否是有效的声明 对于良好且稳定的 API
  • 如何从函数返回矩阵(二维数组)? (C)

    我创建了一个生成宾果板的函数 我想返回宾果板 正如我没想到的那样 它不起作用 这是函数 int generateBoard int board N M i j fillNum Boolean exists True initilize se

随机推荐

  • 盘点12个Python数据可视化库

    大家好 我是小z 这篇文章是关于一本很奈斯的可视化书籍的介绍 老规矩 文末小z简单粗暴的抽奖送出1本 在数据可视化的研究热潮中 如何让数据生动呈现 成了一个具有挑战性的任务 随之也出现了大量的可视化软件 相对于其他商业可视化软件 Pytho
  • C#多线程之BackgroundWorker

    一 BackgroundWorker介绍 我们有时要执行耗时的操作 在该操作未完成之前操作用户界面 会导致用户界面停止响应 解决的方法就是新开一个线程 把耗时的操作放到线程中执行 这样就可以在用户界面上进行其它操作 新建线程可以用 Thre
  • jvm垃圾回收机制

    如何判定一个对象是不是垃圾对象 1 引用计数法 2 根可达性算法 引用计数法 2 可达性分析算法 垃圾回收算法 1 标记清除算法 位置不连续 会产生磁盘碎片 2 复制算法 没有碎片 浪费空间 3 标记整理 没有碎片 效率偏低
  • 算法训练营第十七天(7.29)

    目录 LeeCode513 Find Bottom Left Tree Value LeeCode112 Path Sum LeeCode113 Path Sum ll LeeCode106 Construct Binary Tree fr
  • [C语言]---操作符

    1 算术操作符 的两个操作数必须为整数 3 2 1 3 0 2 1 5 2 移位操作符 左移 lt lt num lt lt 1 num值不变 右移 gt gt 分两种 逻辑移位 左边用0填充 右边丢弃 算术移位 左边用原该值的符号位填充
  • VMware下Ubuntu与宿主Windows共享文件夹

    概述 1 安装VMware Tool 2 设置共享 步骤 开始安装VMware Tool 显示如下画面 如果宿主无法访问外网 可能会出现一个更新失败 可以无视之 通过下列命令解压 执行 分别是下面的tar和sudo的两行 下面是已有vmwa
  • AcWing 372. 棋盘覆盖(二分图&&匈牙利算法)

    输入样例 8 0 输出样例 32 解析 n为100 状压肯定爆 将每个骨牌看成二分图的一个匹配 即查找二分图的一个最大匹配 匈牙利算法 include
  • C# 数据类型_摘自菜鸟教程

    数据类型 值类型 Value types 引用类型 Reference types 对象 Object 类型 动态 Dynamic 类型 字符串 String 类型 指针类型 Pointer types 值类型 Value types 值类
  • CAP的分区容错性

    一直没有理解CAP 中P的分区容错性是什么意思 系统部分节点出现故障后 连接正常节点还可以使用系统提供的服务
  • VS项目中引入dll的方法

    引入dll的方法 方法1 配置属性 gt 调试 gt 环境 输入path 包含dll文件的文件夹路径 方法2 1 将dll文件拷贝到生成的 exe所在的文件夹中 2 项目右键 添加引用 选择dll文件 我用的第二种
  • 【华为OD机试真题】字符串通配符(200分)

    目录 题目 输入描述 输出描述 示例1 示例2 示例3 个人解法 总结 系列文章目录 题目 时间限制 C C 1秒 其他语言2秒 空间限制 C C 32M 其他语言64M 在计算机中 通配符是一种特殊语法 广泛应用于文件搜索 数据库 正则表
  • 挖槽,Sharding-JDBC强制走主库,一不留神就报错了

    点击关注强哥 查看更多精彩文章呀 今天项目中突然告警报错 打出了多条相似的错误日志 查看了下 具体报错内容如下 HintManagerHolder has previous value please clear first 从错误日志我们可
  • 半监督

    半监督学习 transductive learning unlabeled data is the testing data inductive learning unlabeled data is not the testing data
  • ARGB色彩空间模型:ARGB_8888、ARGB_4444、RGB_565、ALPHA_8、ARGB1555

    ARGB是一种色彩空间模式 由RGB色彩空间和Alpha通道组成 RGB即红 Red 绿 Green 蓝 Blue Alpha为透明度参数 数值为0 完全透明 无法被看见 数值为100 表示像素完全不透明 ARGB后跟的数字一般为字面意思
  • uni-app 2.2发布,大幅优化H5端性能体验

    背景 uni app发布以来 已经服务了几十万开发者 让我们意外 或者说惊喜的是 有大量开发者用uni app只编写H5版 并没有多端发布 可参考案例 这其实也符合uni app的初衷 uni app的定位并不是需要多端发布时才用uni a
  • uniapp上拉加载更多功能的简单实现

    https www cnblogs com huihuihero p 13206958 html
  • esp32-s2 wifi

    ESP32 S2 wifi 1 AP 无线接入点 网络的中心节点 无心路由器 这个路由器的特点是不能插入网络 没有接入Internet 只能等待其他设备的连接 只能智能接入 类似于点对点的连接 2 STA站点 每一个连接到无线网络的终端设备
  • 一个域名最多能对应几个IP地址?,一个IP地址可以绑定几个域名?

    一个域名最多能对应几个IP地址 一个IP地址可以绑定几个域名 谢谢 1 也就是说通常情况下一个域名同一时刻只能对应一个IP地址 但是在域名服务商那里 你可以把服务器群里面的多个提供相同服务的服务器IP设置一个域名可以轮询 但是同一时刻 一个
  • 微信小程序页面栈超出导致页面卡死

    微信小程序页面栈不能超出10个 超出10个之后无法进行点击选择跳转 解决方法 跳转的时候 判断之前页面栈里是否存在要跳转的页面 如果存在之前页面 就navigateBack返回之前页面 如果不存在之前页面 判断当前页面栈里是否到10个 如果
  • 软件和硬件数据交互接口的的演进

    编者按AMD Kria SOM及KV260视觉入门套件介绍 电子发烧友在线研讨会 软件和硬件 既相互依存又需要某种程度上的相互独立 通过软件和硬件之间的接口把两者连接在一起 软硬件接口 有很多含义 比如指令集是CPU软件和硬件之间的接口 比