DPDK环境搭建

news2025/1/10 23:49:08

(1)虚拟环境:VMware® Workstation 16 Pro

网上随便下载一个也行

(2)操作系统:ubuntu-22.04-beta-desktop-amd64.iso

下载地址:oldubuntu-releases-releases-22.04安装包下载_开源镜像站-阿里云

(3)DPDK版本:22.07

下载地址:http://fast.dpdk.org/rel/dpdk-22.07.tar.xz

(4)使用VMware安装ubuntu22.04,怎么安装去网上找

安装后的配置,添加两个网络适配器,用于DPDK通信

(5)DPDK的编译

访问链接:Ubuntu22.04 虚拟机中搭建 DPDK 开发环境

缺啥就安装啥

先安装一些依赖的软件包:

apt-get install meson
apt install python3-pyelftools
apt-get install pkg-config

ninja安装:Linux(15)Ubuntu安装ninja构建工具_一歲抬頭的博客-CSDN博客

再编译安装 DPDK:

wget https://fast.dpdk.org/rel/dpdk-22.07.tar.xz
tar xf dpdk-22.07.tar.xz
cd dpdk-22.07
meson  build
cd build
ninja
ninja install

执行完之后所有的库都安装在 /usr/local/lib/x86_64-linux-gnu/ 目录。

可执行程序和脚本都安装在 /usr/local/bin/ 目录。

要卸载只需执行 ninja uninstall 即可。

编译 igb uio 驱动

git clone http://dpdk.org/git/dpdk-kmods
cd dpdk-kmods/linux/igb_uio
make

编译出来 igb_uio.ko

为了验证我们的环境是没问题的,先编译出 l2fwd 程序:

cd examples/l2fwd
make

接着加载 igb_uio 驱动:

cd dpdk-kmods/linux/igb_uio
modprobe uio
insmod igb_uio.ko intr_mode=legacy

注意: 加载驱动时要带着参数intr_mode=legacy,如果不加参数,将会有问题!

分配一些大页内存【这里是1G】:

echo 512 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

绑定两个网卡【虚拟机有 3 个网卡,最后两个网卡供 DPDK 使用】:

ifconfig ens34 down
ifconfig ens35 down
dpdk-devbind.py -b igb_uio ens34 ens35

运行 l2fwd 程序:

cd examples/l2fwd/build/
./l2fwd -l 0-1 -- -p 0x3 -T 1

如果看到以下信息,说明 DPDK 环境没问题!

EAL: Detected CPU lcores: 8
EAL: Detected NUMA nodes: 1
EAL: Detected shared linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: VFIO support initialized
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:02.0 (socket 0)
EAL: Error reading from file descriptor 20: Input/output error
EAL: Probe PCI driver: net_e1000_em (8086:100f) device: 0000:02:03.0 (socket 0)
EAL: Error reading from file descriptor 6: Input/output error
TELEMETRY: No legacy callbacks, legacy socket not created
MAC updating enabled
Lcore 0: RX port 0 TX port 1
Lcore 1: RX port 1 TX port 0
Initializing port 0... EAL: Error enabling interrupts for fd 20 (Input/output error)
done: 
Port 0, MAC address: 00:0C:29:0C:53:91Initializing port 1... EAL: Error enabling interrupts for fd 6 (Input/output error)
done: 
Port 1, MAC address: 00:0C:29:0C:53:9BChecking link statusdone
Port 0 Link up at 1 Gbps FDX Autoneg
Port 1 Link up at 1 Gbps FDX Autoneg
L2FWD: entering main loop on lcore 1
L2FWD:  -- lcoreid=1 portid=1
L2FWD: entering main loop on lcore 0
L2FWD:  -- lcoreid=0 portid=0Port statistics ====================================
Statistics for port 0 ------------------------------
Packets sent:                        0
Packets received:                    0
Packets dropped:                     0
Statistics for port 1 ------------------------------
Packets sent:                        0
Packets received:                    0
Packets dropped:                     0
Aggregate statistics ===============================
Total packets sent:                  0
Total packets received:              0
Total packets dropped:               0
====================================================
^CSignal 2 received, preparing to exit...
EAL: Error disabling interrupts for fd 20 (Input/output error)
Closing port 0... Done
EAL: Error disabling interrupts for fd 6 (Input/output error)
Closing port 1... Done
Bye...

EAL: Error enabling interrupts for fd 20 (Input/output error) 等错误可以忽略。

解绑网卡

两个网卡 ens34 和 ens35 被 DPDK 占用后,ifconfig 里是没有的,要恢复请进行如下操作。

首先查看两个网卡 pci 设备号:

root@ubuntu2204:~# lspci | grep Eth
02:00.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:02.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:03.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)

可看到最后两个网卡设备号是 02:02.0 和 02.03.0。

然后解绑两个网卡的 igb_uio 驱动,绑定 e1000 驱动:

dpdk-devbind.py -u 02:02.0 02:03.0
dpdk-devbind.py -b e1000  02:02.0 02:03.0

最后将网卡up起来:

ifconfig ens34 up
ifconfig ens35 up

(6)DPDK间的发送与接收

上面环境配置完后,克隆出另一个环境,这样就有两个DPDK环境

DPDK接收数据代码:

#include <stdio.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ip.h>
#include <rte_tcp.h>
#include <rte_udp.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

#define NB_MBUF 512
#define MAX_PKT_BURST 32
#define SELF_PROTO_TYPE 0x0888
static struct rte_eth_conf port_conf = {
      .rxmode = {
            .split_hdr_size = 0
      }
};


// cat /proc/interrupts
void init_port(struct rte_mempool *mbuf_pool){
      uint16_t nb_ports = 0;
      int ret = 0;
      int portid = 0;
      struct rte_eth_dev_info dev_info;
      struct rte_ether_addr addr;
      const int num_rx_queues = 1;
      const int num_tx_queues = 0;
      nb_ports = rte_eth_dev_count_avail();
      if(nb_ports == 0){
            rte_exit(EXIT_FAILURE, "No support eth found\n");
      }
      for(portid = 0; portid < nb_ports; portid++){
            ret = rte_eth_macaddr_get(portid, &addr);
            if (ret != 0){
                  rte_exit(EXIT_FAILURE, "macaddr get failed\n");
            } 
            printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
                        " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
                        portid, RTE_ETHER_ADDR_BYTES(&addr));
            ret = rte_eth_dev_info_get(portid, &dev_info);
            ret = rte_eth_dev_configure(portid, num_rx_queues, num_tx_queues, &port_conf);
            ret = rte_eth_rx_queue_setup(portid, 0, 128, rte_eth_dev_socket_id(portid), NULL, mbuf_pool);
            ret = rte_eth_dev_start(portid);
            if (ret < 0) {
                  rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, portid);
            }
      }   
}
/*
      发送方注意设置LP信息
*/
int
main(int argc, char **argv)
{
      int ret;
	unsigned lcore_id;
      int i = 0;
      int portid = 0;
      int nb_rx = 0;
      /* 初始化环境 */
	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");
      /* 创建内存池 */
      struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("my pool", NB_MBUF, 32, 0,
			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
	if (mbuf_pool == NULL){
            return -1;
      }
      init_port(mbuf_pool);
      while(1){
            struct rte_mbuf* pkts_burst[MAX_PKT_BURST];
            nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, MAX_PKT_BURST);
            if(nb_rx == 0){
                  sleep(1);
                  continue;
            }
            printf("recv data start : %d \n", nb_rx);
            for(i = 0; i < nb_rx; i++){
                  // ether
                  struct rte_ether_hdr *hdr = rte_pktmbuf_mtod(pkts_burst[i], struct rte_ether_hdr *);
                  // ip
                  printf("ether_type = %x \n", hdr->ether_type);
                  if(hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)){
                        struct rte_ipv4_hdr *iphdr =  rte_pktmbuf_mtod_offset(pkts_burst[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
                        // upd
                        if(iphdr->next_proto_id == IPPROTO_UDP){
                              // (struct rte_udp_hdr *)RTE_PTR_ADD(iphdr, sizeof(struct rte_ipv4_hdr));
                              struct rte_udp_hdr* udphdr = (struct rte_udp_hdr*)(iphdr + 1);
                              uint16_t length = ntohs(udphdr->dgram_len);
                              *(char*)(udphdr + length) = '\0';
                              struct in_addr addr;
                              addr.s_addr = iphdr->src_addr;
                              printf("src:%s:%d \n", inet_ntoa(addr), ntohs(udphdr->src_port));
                              addr.s_addr = iphdr->dst_addr;
                              printf("dst:%s:%d, %s \n", inet_ntoa(addr), ntohs(udphdr->dst_port), (char*)(udphdr+1));
                        }
                  }else if(hdr->ether_type == rte_cpu_to_be_16(SELF_PROTO_TYPE)){
                        char *data =  rte_pktmbuf_mtod_offset(pkts_burst[i], char *, sizeof(struct rte_ether_hdr));
                        printf("recv data: %s \n", data);
                  }
                  rte_pktmbuf_free(pkts_burst[i]);
            }
      }
      
      return 0;
}

makefile文件

# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2010-2014 Intel Corporation

# binary name
APP = demo1

# all source are stored in SRCS-y
SRCS-y := main.c

PKGCONF ?= pkg-config

# Build using pkg-config variables if possible
ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
$(error "no installation of DPDK found")
endif

all: shared
.PHONY: shared static
shared: build/$(APP)-shared
	ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
	ln -sf $(APP)-static build/$(APP)

PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
# Add flag to allow experimental API as l2fwd uses rte_ethdev_set_ptype API
CFLAGS += -DALLOW_EXPERIMENTAL_API
LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)

ifeq ($(MAKECMDGOALS),static)
# check for broken pkg-config
ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
$(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
$(error "Cannot generate statically-linked binaries with this version of pkg-config")
endif
endif

build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)

build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)

build:
	@mkdir -p $@

.PHONY: clean
clean:
	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
	test -d build && rmdir -p build || true

DPDK发送数据代码

#include <stdio.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ip.h>
#include <rte_tcp.h>
#include <rte_udp.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
#include <rte_memcpy.h>
#include <rte_cycles.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

#define NB_MBUF 512
#define MAX_PKT_BURST 32
#define PKG_LEN 128
#define DST_MAC "005056224E38"
#define SELF_PROTO_TYPE 0x0888
static struct rte_eth_conf port_conf;

// cat /proc/interrupts
void init_port(struct rte_mempool *mbuf_pool){
      uint16_t nb_ports = 0;
      int ret = 0;
      int portid = 0;
      struct rte_eth_dev_info dev_info;
      struct rte_ether_addr addr;
      const int num_rx_queues = 0;
      const int num_tx_queues = 1;
      nb_ports = rte_eth_dev_count_avail();
      if(nb_ports == 0){
            rte_exit(EXIT_FAILURE, "No support eth found\n");
      }
      for(portid = 0; portid < nb_ports; portid++){
            ret = rte_eth_macaddr_get(portid, &addr);
            if (ret != 0){
                  rte_exit(EXIT_FAILURE, "macaddr get failed\n");
            } 
            printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
                        " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
                        portid, RTE_ETHER_ADDR_BYTES(&addr));
            ret = rte_eth_dev_info_get(portid, &dev_info);
            ret = rte_eth_dev_configure(portid, num_rx_queues, num_tx_queues, &port_conf);
            ret = rte_eth_tx_queue_setup(portid, 0, 128, rte_eth_dev_socket_id(portid), NULL);
            ret = rte_eth_dev_start(portid);
            if (ret < 0) {
                  rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, portid);
            }
            ret = rte_eth_promiscuous_enable(portid);
            if (ret != 0) {
                  rte_exit(EXIT_FAILURE, "promiscuous mode enable failed: %s\n", rte_strerror(-ret));
                  return;
            }
      }   
}

void sendData(uint16_t portId, struct rte_mempool *mbuf_pool){
      struct rte_ether_addr addr_src;
      struct rte_ether_addr addr_dst;
      int ret = 0;
      int queue_id = 0;
      int nb_prep = 0;
      int nb_send = 0;
      struct rte_mbuf *pkt = NULL;
      ret = rte_eth_macaddr_get(portId, &addr_src);
      addr_dst.addr_bytes[0] = 0x00;
      addr_dst.addr_bytes[1] = 0x50;
      addr_dst.addr_bytes[2] = 0x56;
      addr_dst.addr_bytes[3] = 0x22;
      addr_dst.addr_bytes[4] = 0x4E;
      addr_dst.addr_bytes[5] = 0x38;
      
      pkt = rte_pktmbuf_alloc(mbuf_pool);
      if(!pkt){
            printf("rte_pktmbuf_alloc faild \n");
            return;
      }
      pkt->data_len = PKG_LEN;
      struct rte_ether_hdr *hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
      // 源地址
      rte_ether_addr_copy(&addr_src, &(hdr->src_addr));
      // 目的地址
      rte_ether_addr_copy(&addr_dst, &(hdr->dst_addr));
      // 帧协议
      hdr->ether_type = rte_cpu_to_be_16(SELF_PROTO_TYPE);
      char* data =  rte_pktmbuf_mtod_offset(pkt, char *, sizeof(struct rte_ether_hdr));
      rte_memcpy(data, "hello", strlen("hello") + 1);
      nb_prep = rte_eth_tx_prepare(portId, queue_id, &pkt, 1); //准备数据
	nb_send = rte_eth_tx_burst(portId, queue_id, &pkt, 1); //发送数据
      // 释放
      rte_pktmbuf_free(pkt);
}

int
main(int argc, char **argv)
{
      int ret;
	unsigned lcore_id;
      int i = 0;
      int portid = 0;
      int nb_rx = 0;
      /* 初始化环境 */
	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");
      /* 创建内存池 */
      struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("my pool", NB_MBUF, 32, 0,
			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
	if (mbuf_pool == NULL){
            return -1;
      }
      init_port(mbuf_pool);
      while(1){
            sendData(portid, mbuf_pool);
            // 1000000微秒 = 1秒
		rte_delay_us(1000000);
      }
      return 0;
}

发送数据代码中,目标MAC地址需要改为接收虚拟机中的MAC

这个MAC在接收数据代码里也会打印,复制即可

makefile文件

# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2010-2014 Intel Corporation

# binary name
APP = send

# all source are stored in SRCS-y
SRCS-y := main.c

PKGCONF ?= pkg-config

# Build using pkg-config variables if possible
ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
$(error "no installation of DPDK found")
endif

all: shared
.PHONY: shared static
shared: build/$(APP)-shared
	ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
	ln -sf $(APP)-static build/$(APP)

PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
# Add flag to allow experimental API as l2fwd uses rte_ethdev_set_ptype API
CFLAGS += -DALLOW_EXPERIMENTAL_API
LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)

ifeq ($(MAKECMDGOALS),static)
# check for broken pkg-config
ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
$(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
$(error "Cannot generate statically-linked binaries with this version of pkg-config")
endif
endif

build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)

build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)

build:
	@mkdir -p $@

.PHONY: clean
clean:
	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
	test -d build && rmdir -p build || true

测试

自己编译就行,make一下

发送数据:

接收数据:

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

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

相关文章

Thymeleaf语法详解

目录 一、Thymeleaf介绍 &#xff08;1&#xff09;依赖 &#xff08;2&#xff09;视图 &#xff08;3&#xff09;控制层 二、变量输出 三、操作字符串 四、操作时间 五、条件判断 六、遍历集合 &#xff08;1&#xff09;迭代遍历 &#xff08;2&#xff09;将遍…

Java————数组

1 、数组 数组可以看成是相同类型元素的一个集合&#xff0c; 在内存中是一段连续的空间。 每个空间有自己的编号&#xff0c;其实位置的编号为0&#xff0c;即数组的下标。 数组是引用类型。 1. 数组的创建 T[] 数组名 new T[N];T&#xff1a;表示数组中存放元素的类型 …

Kakfa - Producer机制原理与调优

Producer是Kakfa模型中生产者组件&#xff0c;也就是Kafka架构中数据的生产来源&#xff0c;虽然其整体是比较简单的组件&#xff0c;但依然有很多细节需要细品一番。比如Kafka的Producer实现原理是什么&#xff0c;怎么发送的消息&#xff1f;IO通讯模型是什么&#xff1f;在实…

对Docker的认识和总结

Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接…

数据结构入门 — 二叉树的概念、性质及结构

本文属于数据结构专栏文章&#xff0c;适合数据结构入门者学习&#xff0c;涵盖数据结构基础的知识和内容体系&#xff0c;文章在介绍数据结构时会配合上动图演示&#xff0c;方便初学者在学习数据结构时理解和学习&#xff0c;了解数据结构系列专栏点击下方链接。 博客主页&am…

学习记忆——英语——字母编码

字母编码表 A&#xff1a;苹果 &#xff1b; B&#xff1a;一支笔或者小男孩boy &#xff1b; C&#xff1a;月亮或者镰刀 &#xff1b; D&#xff1a;笛子或者弟弟或者狗dog &#xff1b; E&#xff1a;大白鹅 &#xff1b; F&#xff1a;斧头 &#xff1b; G&#xff1a;鸽子…

Python:安装Flask web框架hello world示例

安装easy_install pip install distribute 安装pip easy_install pip 安装 virtualenv pip install virtualenv 激活Flask pip install Flask 创建web页面demo.py from flask import Flask app Flask(__name__)app.route(/) def hello_world():return Hello World! 2023if _…

Spring注解家族介绍: @RequestMapping

前言&#xff1a; 今天我们来介绍RequestMapping这个注解&#xff0c;这个注解的内容相对来讲比较少&#xff0c;篇幅会比较短。 目录 前言&#xff1a; RequestMapping 应用场景&#xff1a; 总结&#xff1a; RequestMapping RequestMapping 是一个用于映射 HTTP 请求…

[Linux打怪升级之路]-缓冲区

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习目标&…

SpringCloud Ribbon--负载均衡 原理及应用实例

&#x1f600;前言 本篇博文是关于SpringCloud Ribbon的基本介绍&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力…

深入理解线程安全

引言&#xff1a; 在多线程编程中&#xff0c;线程安全是一个至关重要的概念。线程安全可能到导致数据不一致&#xff0c;应用程序崩溃和其他不可预测的后果。本文将深入探讨线程安全问题的根本原因&#xff0c;并通过Java代码示例演示如何解决这些问题。 线程安全的根本原因 …

element plus Infinite Scroll 无限滚动

欢迎关注我的公众号&#xff1a;夜说猫&#xff0c;让一个贫穷的程序员不靠打代码也能吃饭~ element plus官网中&#xff0c;Infinite Scroll示例使用的是数字&#xff0c;在实际项目运用中&#xff0c;我们更多的是使用json数组进行渲染&#xff0c;所以我们改写v-infinite-sc…

Visual Studio2019报错

1- Visual Studio2019报错 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法 小伙伴们在更新到Visual Studio2019后编译项目时可能遇到过这个错误&#xff1a;“ 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法”&#xff0c;但是我们明明安装了该…

网络安全攻防对抗之隐藏通信隧道技术整理

完成内网信息收集工作后&#xff0c;渗透测试人员需要判断流量是否出得去、进得来。隐藏通信隧道技术常用于在访问受限的网络环境中追踪数据流向和在非受信任的网络中实现安全的数据传输。 一、隐藏通信隧道基础知识 &#xff08;一&#xff09;隐藏通信隧道概述 一般的网络通…

Python图像融合处理和 ROI 区域绘制基础

文章目录 一、图像融合二、图像 ROI 区域定位三、图像属性3.1 shape3.2 size3.3 dtype四、图像通道分离及合并4.1、split()函数4.2 merge()函数五、图像类型转换一、图像融合 图像融合通常是指多张图像的信息进行融合,从而获得信息更丰富的结果,能够帮助人们观察或计算机处理…

微服务保护-隔离

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

SOAP WebService 发布服务成功,但是访问404

原因 我这里是出在路由问题&#xff0c;因为一般我们都会配置WebServiceConfig&#xff0c;WebServiceConfig里又会定义ServletRegistrationBean&#xff0c;用于将一个Servlet注册到Web应用程序中&#xff0c;这里会配置上路径&#xff0c;如下&#xff1a; 但是项目有可能在…

再战SDRAM与资料整理。

总之只要阅读操作手册&#xff0c;按照时序来&#xff0c;完全不难&#xff01; 器件记录&#xff1a; 小梅哥AC620上SDRAM&#xff1a;M12L2561616A-6TG2T 其的存储空间为16M*16256MB&#xff0c;第二行的数字则与其速度等级有关&#xff1b;其分为&#xff1a; 4bank*16bit…

NLP(6)--Diffusion Model

目录 一、Flow-Based General Model 1、概述 2、函数映射关系 3、Coupling Layer 4、Glow 二、Diffusion Model 1、概述 2、前向过程 3、反向过程 4、训练获得噪声估计模型 5、生成图片 三、马尔科夫链 一、Flow-Based General Model 1、概述 Flow-Based General…

C 通过宏定义重定义malloc - free,预防内存泄露

系列文章目录 C模版基础 文章目录 目录 代码地址 相关说明 使用案例 代码地址 GitHub - CHENLitterWhite/CPPWheel: CPP自封装的库 /* * 作者: 干饭小白 * 时间: 2023-09-25 16:00:00:00 * * 说明: * 只能检测 malloc 和 free,无法检测 new delete */ #pra…