基于DPDK的VPP 插件demo代码

VPP的插件编写, 首先要把VPP 工程下载下来, 编译通过。

然后按照example程序的套中来编写插件。

还有一个前提, 就是测试机上已经具备了DPDK 已经可用版本。

1. 下载VPP。

可以从github上下载VPP的指定版本的zip包, 

也可以用git clone的方式直接clone到linux虚拟机上。

git clone -b stable/1801 https://github.com/FDio/vpp.git
 

2. 编译VPP 。

电脑好的话, 半小时能build出来。 内存小可能要一晚上。

cd ./vpp

./extras/vagrant/build.sh && make
编译好后会在./vpp/build-root下出现以下.deb文件 。

安装以下几个即可:

$ dpkg –i vpp-lib_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp-dev_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp-plugins_18.01.2-1~g9b554f3_amd64.deb
 

3. (假设dpdk已经可以用了)

把一个网卡加入到dpdk进行托管。

首先查一下我们有几个网卡。ifconfig

暂时用eth2吧:

lspci |grep -i ethernet 

查看对应的pci 号,

root@ubuntu:/home/king/yubo/vpp/build-root# lspci |grep -i ethernet
02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:06.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
0b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)

目前还不知道 哪个是eth2

我们先把eth2 down掉, 这样dpdk才能托管。

ifconfig eth2 down.

进入dpdk的设置:

export RTE_SDK=/home/bo/dpdk_learnd/dpdk-stable-19.08.2
export RTE_TARGET=x86_64-native-linux-gcc

cd $RTE_SDK
cd usertools
ifconfig eth2 down
./dpdk-setup.sh

先选 [43] 安装一下IGB_UIO

然后[48]查看目前可用的网口

可以看到 eth2的信息如下:

然后按【49 】 把eth2 绑定到igb_uio 驱动。

再按【48】确认已经绑定成功了。

Option: 48


Network devices using DPDK-compatible driver
============================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=igb_uio unused=e1000

Network devices using kernel driver
===================================
0000:02:06.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=eth3 drv=e1000 unused=igb_uio
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=eth0 drv=vmxnet3 unused=igb_uio *Active*
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' if=eth1 drv=vmxnet3 unused=igb_uio *Active*

按【60】 退出DPDK

[60] Exit Script

Option: 60

4. DPDK 准备好了,现在设置VPP 初始化配置。

vi /etc/vpp/startup.conf

修改为以下:

unix {
  interactive cli-listen 127.0.0.1:5002
  nodaemon
  log /tmp/vpp.log
  full-coredump
  cli-listen /run/vpp/cli.sock
  gid vpp
}

api-trace {
  on
}

api-segment {
  gid vpp
}

cpu {

        main-core 0

}

 dpdk {
       

        uio-driver igb_uio
        dev 0000:02:01.0       
}

然后运行VPP 确认VPP 目前工具正常了。

modprobe uio

modprobe igb_uio

echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages

echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages

vpp -c /etc/vpp/startup.conf

启动vpp , 结果启动失败, 报以下错误

## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci,114,2-968%:qroot@ubuntu:/home/king/yubo/dpdk_learnd/dpdk-stable-19.08.2/usertools# vpp -c /etc/vpp/startup.conf 
vlib_plugin_early_init:356: plugin path /usr/lib/vpp_plugins
load_one_plugin:184: Loaded plugin: acl_plugin.so (Access Control Lists)
load_one_plugin:184: Loaded plugin: dpdk_plugin.so (Data Plane Development Kit (DPDK))
load_one_plugin:184: Loaded plugin: flowprobe_plugin.so (Flow per Packet)
load_one_plugin:184: Loaded plugin: gtpu_plugin.so (GTPv1-U)
load_one_plugin:184: Loaded plugin: ila_plugin.so (Identifier-locator addressing for IPv6)
load_one_plugin:184: Loaded plugin: ioam_plugin.so (Inbound OAM)
load_one_plugin:114: Plugin disabled (default): ixge_plugin.so
load_one_plugin:184: Loaded plugin: kubeproxy_plugin.so (kube-proxy data plane)
load_one_plugin:184: Loaded plugin: l2e_plugin.so (L2 Emulation)
load_one_plugin:184: Loaded plugin: lb_plugin.so (Load Balancer)
load_one_plugin:184: Loaded plugin: libsixrd_plugin.so (IPv6 Rapid Deployment on IPv4 Infrastructure (RFC5969))
load_one_plugin:184: Loaded plugin: memif_plugin.so (Packet Memory Interface (experimetal))
load_one_plugin:184: Loaded plugin: nat_plugin.so (Network Address Translation)
load_one_plugin:184: Loaded plugin: pppoe_plugin.so (PPPoE)
load_one_plugin:184: Loaded plugin: stn_plugin.so (VPP Steals the NIC for Container integration)
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/pppoe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/gtpu_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_vxlan_gpe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/nat_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/lb_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/flowprobe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/acl_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/udp_ping_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/stn_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/vxlan_gpe_ioam_export_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/dpdk_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/memif_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/kubeproxy_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_pot_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_export_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_trace_test_plugin.so
dpdk_config:1240: EAL init args: -c 1 -n 4 --huge-dir /run/vpp/hugepages --file-prefix vpp -w 0000:02:06.0 -w 0000:02:01.0 --master-lcore 0 --socket-mem 64 
EAL: 1 hugepages of size 1073741824 reserved, but no mounted hugetlbfs found for that size
EAL: VFIO support initialized
EAL:   Invalid NUMA socket, default to 0
EAL: Error reading from file descriptor 15: Input/output error
EAL: Error reading from file descriptor 15: Input/output error

这是因为dpdk 在绑定对应 网卡后, 初始化时中断功能不支持导致的,

用lspci可以看下对应的网卡驱动。

正常显示为VMXNET3 的网卡是直接 可用于DPDK的。

上边两个82545EM的就不支持。

现在把对应的网卡改成VMXNET3的驱动试下。

把虚拟机的 xx.vmx 配置文件 从左改成右边的配置:

(把e1000都 改成vmxnet3)中间可能要重启下虚拟机和物理机。

再查询发现,已经全部变成vmxnet3的网卡了。

root@ubuntu:/home/# lspci|grep -i ethernet
03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
0b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
13:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
1b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)

现在再重新把VPP的流程走一下。 从DPDK 绑定开始到启动VPP。

我去, 这下就起来了撒:

查看对应网口。

show int

这样就相当于VPP 可以工作了。quit 命令可以退出VPP。

5. 准备VPP 插件文件。

在vpp/src/plugins/目录新建一个文件 夹: pktdumpme

把pktdumpme.c pktdumpme.h pktdumpme_node.c 放到这个目录下。

修改vpp/src下的文件configure.ac , 增加以下这行:

修改plugins 文件 夹下的文件 Makefile.am为以下:

在plugins文件夹下新增pktdumpme.am


# Copyright (c) 2015 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.libpktdumpme_plugin_la_SOURCES =                        \pktdumpme/pktdumpme.c                   \pktdumpme/pktdumpme_node.cnoinst_HEADERS +=                               \pktdumpme/pktdumpme.hvppplugins_LTLIBRARIES += libpktdumpme_plugin.la# vi:syntax=automake

然后回到vpp 根目录下执行:

make wipe

make build    #编译新插件

make run     #deubg 模式启动VPP

这个时候可以看到,VPP 已经把我们新写的插件启动起来了。

我们现在可以看下能不能配置一个网口, 使能Pkt dumpme功能:

现在看, VPP 已经可以把192.168.100.200 这个口收到的报文打印出来了。

6. DEMO 已经成功了, 现在分享一下代码 。

pktdumpme.h  暂时不管内容, 先这么套吧

#ifndef __included_yb_sample_h
#define __included_yb_sample_h#include <vnet/vnet.h>
#include <vnet/ip/ip.h>#include <vppinfra/hash.h>
#include <vppinfra/error.h>
#include <vppinfra/elog.h>typedef struct {u16 msg_id_base; // ???, 这玩意儿也没有用啊vnet_main_t * vnet_main; // ???
} yb_sameple_main_t;extern yb_sameple_main_t yb_sameple_main;
extern vlib_node_registration_t yb_sample_node;#define YB_SAMPLE_PLUGIN_BUILD_VER "1.0" #endif

pktdumpme.c

这个文件 主要是注册插件功能,主要涉及4 层信息:

VLIB, VNET, PLUGIN, CLI_command. 

#include <vnet/plugin/plugin.h>
#include <pktdumpme/pktdumpme.h>yb_sameple_main_t yb_sameple_main;static clib_error_t * yb_sample_command_ena_disa_fn(vlib_main_t *vm, unformat_input_t * input,vlib_cli_command_t * cmd) // not use 
{// need parse 2 argument, interface index and enable flagint interfaceIdx = -1;int enableFlag = 1; // default on// traverse all input stringswhile(unformat_check_input(input) != UNFORMAT_END_OF_INPUT){if(unformat(input, "disable")){enableFlag = 0;}else if(unformat(input, "%U", unformat_vnet_sw_interface, yb_sameple_main.vnet_main, &interfaceIdx)) // 应该是看这个输入是某一个网口, 是的话把Index存到 变量中。 后边再看下。{;			}elsebreak;}if(-1 == interfaceIdx)return clib_error_return(0, "please specify a right interface name.\n");//开始对相应接口进行设置。if(pool_is_free_index(yb_sameple_main.vnet_main->interface_main.sw_interfaces, interfaceIdx))return 0;// 调用库函数操作这个nodevnet_feature_enable_disable("ip4-unicast", "yb_sample", interfaceIdx, enableFlag, 0, 0);return 0;}// 命令行注册
VLIB_CLI_COMMAND(yb_sample_command, static)=
{.path = "pkt dumpme",.short_help = "pkt dumpme <interface-name> [disable]",.function = yb_sample_command_ena_disa_fn,
};// plugin注册
VLIB_PLUGIN_REGISTER() =
{.version = YB_SAMPLE_PLUGIN_BUILD_VER,.description = "yb sample hello world", 
};// 设置VLIB 初始化函数
static clib_error_t * yb_sample_init(vlib_main_t* vm)
{yb_sameple_main.vnet_main = vnet_get_main();return 0;
}VLIB_INIT_FUNCTION(yb_sample_init);// pktdump功能要用到网络相关的功能 , 所以要配置一下当前plugin要在nvet的指定位置运行。
// 指定yb_sample node的初始化参数, 应该是在arc "ip4-unicast" 下, node名字为 yb-sample, 
// 运行在ip4-lookup node之前。后边会指定ip4-lookup为next node中的[0]
VNET_FEATURE_INIT(yb_sample, static) =   
{.arc_name = "ip4-unicast",.node_name = "yb_sample",.runs_before = VNET_FEATURES("ip4-lookup"),
};

pktdumpme_node.c

这个就是实现报文回显的主要代码: 从frame中取出所有的packet vectore, 然后进行打印, 然后再push到下一frame中的buffer中。 这里ip4_lookup 就是下一个Node. 这个是VPP 自带的Node, 以后慢慢会熟悉。 另外关于push到下一个node还是下一个frame, 我觉得应该是一个意思, 以后学习深入了应该能确认。 注释有可能不准备, 读者自行消化,彼人也是第一次弄。

#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
#include <vnet/ethernet/ethernet.h>
#include <vppinfra/error.h>
#include <pktdumpme/pktdumpme.h>typedef enum
{CK_SAMPLE_NEXT_IP4,CK_SAMPLE_DROP,CK_SAMPLE_NEXT_N,
} yb_sample_next_t;typedef struct
{u32 next_index;u32 sw_if_index;u8 new_src_mac[6];u8 new_dst_mac[6];
} yb_sample_trace_t;#define foreach_yb_sample_error \
_(SHOWED, "show packets processed")typedef enum
{
#define _(sym,str) SAMPLE_ERROR_##sym,foreach_yb_sample_error
#undef _SAMPLE_N_ERROR,
} yb_ssample_error_t;static char *yb_sample_error_strings[] = {
#define _(sym, str) str,foreach_yb_sample_error
#undef _
};// extern vlib_node_registration_t yb_sample_node; // 不打开 能编译过
static u8 *
format_yb_sample_trace (u8 * s, va_list * args)
{s = format(s, "To Do!\n");return s;
}// 定义打印报文的主函数
static uword yb_sample_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
{u32 n_left_in_frame, *thisDataStart, *nextNodeDataStart;u16 nextNodeIndex = 0;// 取出当前node 的数据的位置(在from中), 有多少个数据。thisDataStart = vlib_frame_vector_args(frame);n_left_in_frame = frame->n_vectors;nextNodeIndex   = node->cached_next_index;// 取出默认下一node index.// 解析所有的数据, 并push到下一个Node[0]中。while(n_left_in_frame > 0){u32 n_left_in_next;//先获取下一NODE 可以存数的信息, start, Nvlib_get_next_frame(vm, node, nextNodeIndex, nextNodeDataStart, n_left_in_next);while(n_left_in_frame > 0 && n_left_in_next > 0){// 把index指向的buffer, 转为m_buff, 然后解析, 再Push给下一node。vlib_buffer_t *bp0;u32 bi0, nextNode = 0;bi0 = thisDataStart[0];nextNodeDataStart[0] = thisDataStart[0];n_left_in_frame -= 1;n_left_in_next  -= 1;thisDataStart     += 1;nextNodeDataStart += 1;bp0 = vlib_get_buffer(vm, bi0);void* data = vlib_buffer_get_current(bp0);{   int i;for(i = 0; i <32; i++){printf("%02x ", *((u8*)data + i));}printf("\n");}vlib_validate_buffer_enqueue_x1(vm, node, nextNodeIndex, nextNodeDataStart, n_left_in_next, bi0, nextNode);}vlib_put_next_frame(vm, node, nextNodeIndex, n_left_in_next); // 应该是理解为next frame 不是next node.或者说node和frame是一对一的。}// 返回处理了多少个数据。return frame->n_vectors;  // 一定要返回这个吗?
}// 注册node.
VLIB_REGISTER_NODE(yb_sample_node) = 
{.name = "yb_sample",.function = yb_sample_node_fn,.vector_size = sizeof(u32),.format_trace = format_yb_sample_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors = ARRAY_LEN(yb_sample_error_strings),.error_strings = yb_sample_error_strings,.n_next_nodes = 2,.next_nodes = {[0] = "ip4-lookup",[1] = "error-drop",},
};

至此, 第一个demo 插件就完成了。

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

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

相关文章

2024年租用阿里云服务器多少钱一年?连夜整理分享

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

__ne__()函数详解

在Python中&#xff0c;ne 是一个特殊方法&#xff0c;用于定义不等于&#xff08;!&#xff09;操作符的行为。当你使用 ! 操作符来比较两个类的实例时&#xff0c;Python会自动调用这个方法。如果这个方法没有在你的类中定义&#xff0c;那么 ! 操作符会使用 eq 方法的结果来…

【C++】C++ primer plus 第十二章--类和动态内存分配

动态内存和类 关于静态数据成员 类之作声明&#xff0c;不分配内存&#xff0c;因此静态成员变量在类中不能进行初始化&#xff0c;需要在类外进行。特殊情况&#xff1a; 存在可以在类中声明静态成员并初始化的情况&#xff0c;成员类型为const整型或者const枚举类型。 特殊…

软考高级架构师:嵌入式系统的内核架构

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

2024/4/1—力扣—二叉树的最近公共祖先

代码实现&#xff1a; 思路&#xff1a; 递归判断左子树和右子树&#xff0c;查找p或者q是否在当前节点的子树上 1&#xff0c;在同一子树上&#xff0c;同一左子树&#xff0c;返回第一个找到的相同值&#xff0c;同一右子树上&#xff0c;返回第一个找到的相同值 2&#xff0…

Oracle23免费版简易安装攻略

installation-guide 1 安装 root用户下 wget https://yum.oracle.com/repo/OracleLinux/OL8/developer/x86_64/getPackage/oracle-database-preinstall-23c-1.0-1.el8.x86_64.rpm wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23c-1…

UML 绘制工具 starUML 入门介绍

拓展阅读 常见免费开源绘图工具 OmniGraffle 创建精确、美观图形的工具 UML-架构图入门介绍 starUML UML 绘制工具 starUML 入门介绍 PlantUML 是绘制 uml 的一个开源项目 UML 等常见图绘制工具 绘图工具 draw.io / diagrams.net 免费在线图表编辑器 绘图工具 excalidr…

linux lua版本升级

要在Linux上升级Lua到5.4版本&#xff0c;你需要执行以下步骤&#xff1a; 1、下载Lua 5.4源代码&#xff1a; 首先&#xff0c;你需要从Lua的官方网站下载Lua 5.4的源代码。你可以访问Lua的官方网站或使用wget或curl命令从命令行下载。 wget http://www.lua.org/ftp/lua-5.4.x…

工具推荐-针对Nacos利器-NacosExploitGUI_v4.0

Nacos是由阿里所开发的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 工具简介 集成Nacos的各种poc Nacos控制台默认口令漏洞(nacos,nacos)Nacostoken.secret.key默认配置(QVD-2023-6271)Nacos-clientYaml反序列化漏洞Nacos Jraft Hessian反序列化漏洞…

代码随想录算法训练营第46天|139.单词拆分|关于多重背包,你该了解这些!|背包问题总结篇!

代码随想录算法训练营第46天|139.单词拆分|关于多重背包&#xff0c;你该了解这些&#xff01;|背包问题总结篇&#xff01; 详细布置 关于 多重背包&#xff0c;力扣上没有相关的题目&#xff0c;所以今天大家的重点就是回顾一波 自己做的背包题目吧。 139.单词拆分 视频讲…

PET-SQL:基于大模型的两阶段Text2SQL方法

简介 PET-SQL出自论文《PET-SQL: A Prompt-enhanced Two-stage Text-to-SQL Framework with Cross-consistency》&#xff0c;将基于大模型的Text2SQL分为两个阶段进行&#xff0c;在第一阶段使用数据表schema信息、数据表采样数据、相似问答问答对生成初步的SQL(PreSQL)&…

【边缘智能】00_边缘计算发展背景

本系列是个人学习《边缘就算基础知识入门》的笔记&#xff0c;仅为个人学习记录&#xff0c;欢迎交流&#xff0c;感谢批评指正 移动物联设备产生海量数据&#xff0c;数据密集型移动智能应用&#xff0c;计算密集、动态性高&#xff0c;实时性强 传统云计算架构 基于广域互联…

大学课堂点名程序

大学课堂点名程序 from gtts import gTTS import os import tkinter as tk import pygame import csv import random from datetime import datetime from tkinter import messagebox from tkinter import simpledialog input_data="student1" def langDu(text):tts…

matrix-breakout-2-morpheus 靶机渗透

信息收集&#xff1a; 1.nmap存活探测&#xff1a; nmap -sn -r 192.168.10.1/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-06 12:13 CST Nmap scan report for 192.168.10.1 Host is up (0.00056s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap…

鸿蒙内核源码分析 (双向链表篇) | 谁是内核最重要结构体

双向链表是什么&#xff1f; 谁是鸿蒙内核最重要的结构体 &#xff1f; 一定是: LOS_DL_LIST(双向链表)&#xff0c; 它长这样。 typedef struct LOS_DL_LIST {struct LOS_DL_LIST *pstPrev; /**< Current nodes pointer to the previous node | 前驱节点(左手)*/struct L…

Qt实现Kermit协议(四)

3 实现 3.3 KermitRecvFile 该模块实现了Kermit接收文件功能。 序列图如下&#xff1a; 3.3.1 KermitRecvFile定义 class QSerialPort; class KermitRecvFile : public QObject, public Kermit {Q_OBJECT public:explicit KermitRecvFile(QSerialPort *serial, QObject *…

题目 1847: 字符串中间和后边*号删除

题目描述: 假定输人的字符串中只包含字母和*号。请编写函数fun(  )&#xff0c;它的功能是&#xff1a;除了字符串前导的*号之外&#xff0c;将串中其他*号全部删除。在编写函数时&#xff0c;不得使用C语言提供的字符串函数。 代码: package lanqiao;import java.math.Bi…

面试(03)————多线程和线程池

一、多线程 1、什么是线程?线程和进程的区别? 2、创建线程有几种方式 &#xff1f; 3、Runnable 和 Callable 的区别&#xff1f; 4、如何启动一个新线程、调用 start 和 run 方法的区别&#xff1f; 5、线程有哪几种状态以及各种状态之间的转换&#xff1f; 6、线程…

RIP协议

路由信息协议。 分为v1和v2 1、标准的距离矢量型协议 2、使用跳数作为度量&#xff0c;默认优先级为100 3、v1为有类别版本&#xff0c;v2为无类别版本&#xff08;无类别自定义掩码&#xff09; 4、周期更新触发更新。 v1和v2的区别 1、v1不携带子网掩码——不支持子网划…

极越夏一平反思:论技术我们很能打,要解决品牌认知问题

作者 |张祥威 编辑 |德新 今年起&#xff0c;新能源汽车竞争强度明显再上一个台阶。 华为主导下的问界强势逆袭&#xff0c;雷军亲自坐镇的小米汽车在发布后斩获丰厚的大定订单&#xff0c;给其它汽车品牌带来压力。3月末&#xff0c;在小米发布会前几日&#xff0c;极越在北…