当前位置: 首页 > news >正文

为raspberrypi编译bpftrace调试工具

基于eBPF的嵌入式应用调试

笔者之前写过几篇有关于使用eBPF调试Linux内核和应用的博客,其中提到,在嵌入式设备上使用BCC或bpftrace是不可行的;主要原因在于嵌入式设备的资源有限,而这两个调试工具依赖python/clang/llvm等库,需要将脚本编译为eBPF字节码加载入Linux内核来执行。然而,随着嵌入式设备的性能越来越强,板载资源越来越多,在嵌入式设备上运行bpftrace工具已成为可能。本文整理了笔者为raspberrypi 4设备编译bpftrace工具的过程,按照这些操作,笔者为工作中的嵌入式设备也制作了可用的bpftrace调试工具。

另外,22.04版本的Ubuntu系统自带的bpftrace已经不能用了,主要的原因是它不带符号表(strip -s);本文的内容也可用于PC端的bpftrace工具编译构建:

root@ubuntu:/usr/sbin# uname -a
Linux ubuntu 5.15.0-97-generic #107-Ubuntu SMP Wed Feb 7 13:26:48 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu:/usr/sbin# ./execsnoop.bt
Attaching 3 probes...
ERROR: Could not resolve symbol: /proc/self/exe:BEGIN_trigger

编译使用的设备

首先,笔者使用的raspberrypi 4可插入两张TF卡,两张卡分别安装了debian系统和笔者编译的openwrt系统,二者的Linux内核版本大致相同,均为6.1版本。其次,树莓派设备的内存大小为2GB,这一点非常重要;因为bcc/bpftrace是由C++编写的,编译过程非常耗内存(笔者使用clang编译器构建)。最后,笔者是为了在openwrt系统中使用bpftrace,因此要求在构建openwrt系统时,选择glibc库。

零,安装clang编译器

编译在是树莓派的debian系统上完成的。需要按照apt.llvm.org的说明操作来安装,笔者选择了安装clang-10编译器:

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 10

之后,我们需要在debian安装其他依赖库(而不编译所有的依赖库,否则耗时太久了)。以下需要安装的库,是在raspberrypi/openwrt系统上缺少的,后面会直接复制到安装有openwrt系统的TF卡上:

sudo apt install flex bison zlib1g-dev liblzma-dev libbz2-dev cmake \libzstd-dev dwarves build-essential python3-setuptools libpython3-dev

一,编译elfutils

笔者下载了最新版本的elfutils,它提供了libelf依赖库,该软件包的配置、编译操作如下:

../configure --prefix=/opt/bpftrace CC=clang-10 CXX=clang++-10 \CFLAGS='-Wall -fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -Wno-unused-parameter' \CXXFLAGS='-Wall -fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -Wno-unused-parameter' \--disable-nls --enable-libdebuginfod=dummy --disable-debuginfod --with-zlib --with-lzma \--with-bzlib --with-zstd LDFLAGS='-Wl,-rpath=/opt/bpftrace/lib'
make && sudo make install

以上配置完成后,再执行make && sudo make install即可安装。

二,编译libbpf库

这里需要强调的是,依笔者的经验,libbpf库以及bcc、bpftrace版本的选择,不能任意;一定要根据Linux内核版本来选择。例如,树苺派的Linux内核版本为6.1,那么确认该版本内核的(初始)发布日期(是2023年初发布的),然后选择时间上相近的libbpf库。这里笔者选择的版本为libbpf-1.2.2。然而工作中,笔者因使用的嵌入式设备比较老,使用的版本为0.1.1

该库的编译操作如下:

cd $HOME ; tar -zxf libbpf-1.2.2.tar.gz
cd libbpf-1.2.2/src
make V=1 PREFIX=/opt/bpftrace CC=clang-10 CFLAGS='-fPIC -O2 -ggdb -Wall -fno-omit-frame-pointer -I/opt/bpftrace/include' LDFLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib'
sudo make V=1 PREFIX=/opt/bpftrace CC=clang-10 CFLAGS='-fPIC -O2 -ggdb -Wall -fno-omit-frame-pointer -I/opt/bpftrace/include' LDFLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' install

注意,以上编译的库在debian/arm64系统下会被安装到/opt/bpftrace/lib64路径下,需要移到/opt/bpftrace/lib路径下,并修改/opt/bpftrace/lib/pkgconfig/libbpf.pc文件。

三,安装cereal头文件

早期的bpftrace工具不依赖该库,但现在是需要了,笔者选择了cereal-1.3.2.tar.gz版本:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer' \-DBUILD_DOC=OFF -DBUILD_SANDBOX=OFF -DSKIP_PERFORMANCE_COMPARISON=ON -DBUILD_TESTS=OFF ..
sudo make install

注意,该库以头文件的形式提供,以上不会有动态库编译生成。

四,编译bcc

bcc的版本为v0.27.0,笔者已验证最新版本的bcc编译得到的bpftrace存在异常。需要注意的是,笔者下载的源代码文件名为bcc-src-with-submodule.tar.gz。以下是配置、编译安装的操作:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include' \-DCMAKE_EXE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_MODULE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_SHARED_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DENABLE_LLVM_SHARED=ON -DENABLE_TESTS=OFF -DRUN_LUA_TESTS=OFF -DENABLE_LIBDEBUGINFOD=OFF ..
make && sudo make install

编译完成后,笔者删除了所有的静态库(因为笔者希望所有的库是动态链接的):sudo rm -rf /opt/bpftrace/lib/*.a。注意,这个编译过程比较耗时,大约持继在一小时以上。因rasbperrypi 4内存有2GB,上面可以make -j2来编译加速。

五,编译bpftrace

笔者选择的bpftrace版本为v0.17.1(正如上面提到的,笔者验证最新版本的bpftracearm64/linux-6.1系统下运行不正常。配置、编译安装的操作如下:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include -I${HOME}/libbpf-1.2.2/include -I${HOME}/libbpf-1.2.2/include/uapi' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include -I${HOME}/libbpf-1.2.2/include -I${HOME}/libbpf-1.2.2/include/uapi' \-DCMAKE_EXE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_MODULE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_SHARED_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DUSE_SYSTEM_BPF_BCC=ON -DSTATIC_LINKING=OFF -DALLOW_UNSAFE_PROBE=ON -DBUILD_TESTING=OFF ..
make && sudo make install

需要注意的是,上面的编译选项,直接指定了libbpf-1.2.2头文件包含的路径。至此,笔者的编译就结束了,接下来将编译结果复制到安装有openwrt系统的TF卡中。

在raspberrypi/openwrt系统下使用bpftrace

首先,除了/opt/bpftrace外,笔者从树莓派的debian系统中复制了以下库到openwrt系统:

root@OpenWrt:/lib/aarch64-linux-gnu# ls -lh -t | head -n 8
-rw-r--r--    1 root     root       64.8M Sep  9 22:40 libLLVM-10.so.1
-rw-r--r--    1 root     root       65.0K Sep  9 22:42 libbz2.so.1.0
-rw-r--r--    1 root     root       27.7M Sep  9 22:41 libclang-10.so.1
-rw-r--r--    1 root     root      179.1K Sep  9 22:43 libedit.so.2
-rw-r--r--    1 root     root       30.2K Sep  9 22:42 libffi.so.6
-rw-r--r--    1 root     root      130.2K Sep  9 22:41 liblzma.so.5
-rw-r--r--    1 root     root      158.6K Sep  9 22:43 libtinfo.so.5
-rw-r--r--    1 root     root      405.8K Sep  9 22:41 libzstd.so.1

然后,笔者为树莓派的内核使能了相关的内核选项,详见此处的详细说明。还有,bpftrace的正常运行,可能还需要访问内核的头文件,这就需要使能CONFIG_IKHEADERS=m,在树莓派启动后,手动加载该内核模块:insmod kheaders.ko。最后,笔者在树莓派的openwrt系统下使用bpftrace的结果如下:

root@OpenWrt:~# insmod kheaders.ko
module is already loaded - kheaders
root@OpenWrt:~# uname -a
Linux OpenWrt 6.1.50 #0 SMP Fri Sep  1 21:45:47 2023 aarch64 GNU/Linux
root@OpenWrt:~# /opt/bpftrace/bin/bpftrace --info
SystemOS: Linux 6.1.50 #0 SMP Fri Sep  1 21:45:47 2023Arch: aarch64Buildversion: v0.17.1LLVM: 10.0.1unsafe uprobe: nobfd: nolibdw (DWARF support): yeslibbpf: failed to find valid kernel BTF
Kernel helpersprobe_read: yesprobe_read_str: yesprobe_read_user: yesprobe_read_user_str: yesprobe_read_kernel: yesprobe_read_kernel_str: yesget_current_cgroup_id: yessend_signal: yesoverride_return: noget_boot_ns: yesdpath: noskboutput: noKernel featuresInstruction limit: 1000000Loop support: yesbtf: nomap batch: yesuprobe refcount (depends on Build:bcc bpf_attach_uprobe refcount): yesMap typeshash: yespercpu hash: yesarray: yespercpu array: yesstack_trace: yesperf_event_array: yesProbe typeskprobe: yestracepoint: yesperf_event: yeskfunc: noiter:task: noiter:task_file: nokprobe_multi: noraw_tp_special: yesroot@OpenWrt:~# cd /opt/bpftrace/share/bpftrace/tools/
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools# ls
bashreadline.bt    gethostlatency.bt  runqlen.bt         tcpdrop.bt
biolatency.bt      killsnoop.bt       setuids.bt         tcplife.bt
biosnoop.bt        loads.bt           ssllatency.bt      tcpretrans.bt
biostacks.bt       mdflush.bt         sslsnoop.bt        tcpsynbl.bt
bitesize.bt        naptime.bt         statsnoop.bt       threadsnoop.bt
capable.bt         old                swapin.bt          undump.bt
cpuwalk.bt         oomkill.bt         syncsnoop.bt       vfscount.bt
dcsnoop.bt         opensnoop.bt       syscount.bt        vfsstat.bt
doc                pidpersec.bt       tcpaccept.bt       writeback.bt
execsnoop.bt       runqlat.bt         tcpconnect.bt      xfsdist.bt
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools# /opt/bpftrace/bin/bpftrace ./execsnoop.bt
libbpf: failed to find valid kernel BTF
libbpf: failed to find valid kernel BTF
Attaching 3 probes...
TIME(ms)   PID   ARGS
26138      2490  /etc/init.d/firewall reload
26168      2502  readlink /etc/init.d/firewall
26170      2503  basename /etc/init.d/firewall
26172      2504  flock -n 1000
26174      2505  flock 1000
26178      2506  readlink /etc/init.d/firewall
26181      2507  readlink /etc/init.d/firewall
26183      2508  basename /etc/init.d/firewall
26186      2509  flock -n 1000
26188      2510  fw4 reload
26191      2511  flock -x 1000
26193      2512  rm -f /var/run/fw4.state
26195      2513  utpl -S /usr/share/firewall4/main.uc
26195      2514  nft -f /dev/stdin
26303      2515  sh -c /usr/sbin/nft --terse --json list flowtables inet
26305      2515  /usr/sbin/nft --terse --json list flowtables inet
26393      2516  utpl -S /usr/share/firewall4/main.uc
29341      2517  /etc/init.d/firewall status
29371      2529  readlink /etc/init.d/firewall
29373      2530  basename /etc/init.d/firewall
29375      2531  flock -n 1000
29377      2532  flock 1000
29381      2533  readlink /etc/init.d/firewall
29384      2534  basename /etc/init.d/firewall
29387      2537  jsonfilter -e @["firewall"]
29388      2539  jshn -w
29391      2540  ubus call service list { "name": "firewall" }
29397      2543  jsonfilter -e $.instances
63078      2544  /etc/init.d/network status
63108      2556  readlink /etc/init.d/network
63110      2557  basename /etc/init.d/network
63112      2558  flock -n 1000
63114      2559  flock 1000
63118      2560  readlink /etc/init.d/network
63121      2561  basename /etc/init.d/network
63124      2564  jsonfilter -e @["network"]
63125      2566  jshn -w
63128      2567  ubus call service list { "name": "network" }
63134      2570  jsonfilter -e $.instances
63137      2571  jsonfilter -s { "instance1": { "running": true, "pid": 769, "command": [ "\/sbin\/netifd" ], "term_timeout": 5,
"limits": { "core": "unlimited" }, "respawn": { "threshold": 3600, "timeout": 5, "retry": 5 } } } -e $[*].running
^C
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools#

至此,可以说明我们编译的bpftrace工具可以正常工作了。

相关文章:

为raspberrypi编译bpftrace调试工具

基于eBPF的嵌入式应用调试 笔者之前写过几篇有关于使用eBPF调试Linux内核和应用的博客,其中提到,在嵌入式设备上使用BCC或bpftrace是不可行的;主要原因在于嵌入式设备的资源有限,而这两个调试工具依赖python/clang/llvm等库&…...

分段线性化问题探析

目录 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 4 matlab测试结果说明 5 分段线性化应用 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 clc;clear all; gn10;tn1; x_pfsdpvar(1, t…...

从零学算法2917

2917.给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 nums 中的 K-or 是一个满足以下条件的非负整数: 只有在 nums 中,至少存在 k 个元素的第 i 位值为 1 ,那么 K-or 中的第 i 位的值才是 1 。 返回 nums 的 K-or 值。 注意 &#xf…...

[HackMyVM] 靶场 Wave

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…...

云渲染平台都开始涨价了?2024年性价比高的云渲染平台推荐

最近部分云渲染平台开始涨价,不论是通过调整机器性能,还是直接提价,都会对成本产生影响。这对已经习惯了平台价格的用户来说,并不是一件好事。这里举一些例子: 比如平台A,原“首小时渲染0.66元模式”已经下…...

搜索-BFS Meteor Shower S(流星雨)

Meteor Shower S(流星雨) 题目连接 题目描述 贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星…...

RabbitMQ实战:Springboot集成RabbitMQ并验证五种消息模型

这目录 一、添加依赖二、配置文件中添加RabbitMQ访问配置三、消息生产者代码四、消息消费者代码五、验证参考资料 一、添加依赖 <!--AMQP依赖&#xff0c;包含RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>s…...

配置与管理防火墙

配置与管理防火墙 1&#xff0c;概念&#xff1a;设置在不同网络或网络安全域之间的一系列部件的组合。 2&#xff0c;功能&#xff1a;保护内网中易手攻击的服务&#xff1b;控制内外网之间网络系统的访问&#xff1b;隐藏内网的IP地址及结构的细节&#xff0c;提高网络保护…...

【SpringBoot】-- 实现本地文件/图片上传到服务器生成url地址

在java项目中你可能会有以下需求&#xff1a;用户上传本地图片&#xff0c;然后展示在网页上。本篇文章将使用阿里云oss实现上传图片到oss&#xff0c;oss生成url。 一、准备工作 首先进入阿里云&#xff0c;按如下操作 进入创建页面&#xff0c;修改读写权限为公共读 然后进…...

计算机基础专升本笔记十四-计算机网络基础(一)

计算机基础专升本笔记十四-计算机网络基础&#xff08;一&#xff09; 一、计算机网络的发展历程 第一代计算机网络&#xff08;数据通信&#xff09; 以数据通信为主的第一代计算机网络。主要是指美国军方用于防控系统的一种联机系统。它只是计算机网络的雏形。 第二代计算…...

【华为OD机试】转盘寿司【C卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 寿司店周年庆,正在举办优惠活动回馈新老客户。 寿司转盘上总共有 n 盘寿司,prices[i] 是第 i 盘寿司的价格, 如果客户选择了第 i 盘寿司,寿司店免费赠送客户距离第 i 盘寿司最近的下一…...

使用Node JS获取WI-FI密码

演示效果 全局安装wifi-password-cli依赖 shell 复制代码 npm install wifi-password-cli -g # or npx wifi-password-cli 使用 shell 复制代码 $ wifi-password [network-name] $ wifi-password 12345678 $ wifi-password 办公室wifi a1234b2345 觉得Node.js很神奇是…...

先缓存第二集抖音接入 ,最近加班猛,就分享简单的知识,如何使用:关于使用replace的用法正则表达式

1、需求&#xff1a;比如在cocos creator策划让你制作一个预制体&#xff0c;标题要读取配置&#xff0c;然后中间显示的内容要滚动的&#xff0c;要做成一个通用的&#xff0c;然后给到的配置表是这样子的: 配置表&#xff1a;假设字段是这样子的 content "内容标题&…...

企微hook源码

企微hook源码已经在QQ群内开源。速度进群下载&#xff0c;避免和谐。 QQ群&#xff1a;649480745...

vsphere虚拟机迁移是灰色如何解决

vsphere虚拟机迁移是灰色如何解决 问题描述&#xff1a; 在vsphere中&#xff0c;迁移虚拟机时迁移按钮是灰色&#xff0c;无法迁移&#xff0c;关机之后也无法迁移 虚拟机按钮为灰色 找到虚拟机存储对应的位置&#xff0c;查询是否有.vmx虚拟机文件 查询中发现有.vmx文件存…...

swift 闭包捕获列表

以下函数会打印出什么&#xff1f; var car "Benz" let closure { [car] in print("I drive \(car)") } car "Tesla" closure() 因为 clousre 已经申明将 car 复制进去了&#xff08;[car]&#xff09;&#xff0c;此时clousre 里的 car…...

JavaWeb04-Request,Response

目录 一、Request&#xff08;请求&#xff09; 1.作用 2.继承体系 3.获取请求数据 &#xff08;1&#xff09;请求行 &#xff08;2&#xff09;请求头 &#xff08;3&#xff09;请求体&#xff08;POST&#xff09; &#xff08;5&#xff09;Request通用方式获取请求…...

使用 Docker 部署 Fiora 在线聊天室平台

一、Fiora 介绍 Fiora 简介 Fiora 是一款开源免费的在线聊天系统。 GitHub&#xff1a;https://github.com/yinxin630/fiora Fiora 功能 注册账号并登录&#xff0c;可以长久保存你的数据加入现有群组或者创建自己的群组&#xff0c;来和大家交流和任意人私聊&#xff0c;并添…...

Unity Samples和帧动画的问题

拖动序列帧图片和自己创建clip的帧率不同 我今天在创建帧动画的时候用了两种方式第一种是直接拖动序列帧图片到Hierachy&#xff0c;然后生成的第二种是这样我发现两者播放的动画速率不一样最后查了半天查不到原因。最后发现是Samples的原因&#xff0c;而且Unity把Samples这个…...

几何工具的使用

Geometry - Creation 创建几何 CogCreateCircleTool&#xff1a;创建圆CogCreateEllipseTool:创建椭圆CogCreateLineBisectPointsTool&#xff1a;带有两个点的平行线CogCreateLineParallelTool:在某一点创建某条线的平行线CogCreateLinePerpendicularTool:在某一点创建某条线…...

sudo command not found

文章目录 一句话Intro其他操作 一句话 sudo 某命令 改成 sudo -i 某命令 试试。 -i 会把当前用户的环境变量带过去&#xff0c;这样在sudo的时候&#xff0c;有更高的权限&#xff0c;有本用户的环境变量(下的程序命令)。 -i, --login run login shell as the target user; a …...

1.【Labview白话系列】Labview数组精讲

题主经过写文章一段时间的发现&#xff0c;许多同学对该软件的理解和编程能力是不太一样的&#xff0c;有些知识相对一些同学较为简单&#xff0c;但是有些同学提问就比较困难。那么针对这个问题&#xff0c;题主打算出一期说白话系列的专栏&#xff0c;在该栏目中用最通俗的大…...

ANTLR4规则解析生成器(三):遍历语法分析树

文章目录 1 词法分析2 语法分析3 遍历语法分析树3.1 Listener3.2 Visitor 4 总结 1 词法分析 词法分析就是对给定的字符串进行分割&#xff0c;提取出其中的单词。 在antlr4中&#xff0c;词法规则的名称的首字母需要大写&#xff0c;右侧必须是终结符&#xff0c;通常将词法…...

OpenCV实现目标追踪

目录 准备工作 语言&#xff1a; 软件包&#xff1a; 效果演示 代码解读 &#xff08;1&#xff09;导入OpenCV库 &#xff08;2&#xff09;使用 cv2.VideoCapture 打开指定路径的视频文件 &#xff08;3&#xff09;使用 vid.read() 读取视频的第一帧&#xff0c;ret…...

【剑指offer--C/C++】JZ6 从尾到头打印链表

一、题目 二、本人思路及代码 直接在链表里进行翻转不太方便操作&#xff0c;但是数组就可以通过下标进行操作&#xff0c;于是&#xff0c; 思路1、 先遍历链表&#xff0c;以此存到vector中&#xff0c;然后再从后往前遍历这vector,存入到一个新的vector&#xff0c;就完成…...

算法-买卖股票的最佳时机

1、题目来源 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 2、题目描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖…...

【大数据】Flink SQL 语法篇(十):EXPLAIN、USE、LOAD、SET、SQL Hints

《Flink SQL 语法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 语法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 语法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 语法篇&#xff08;三&…...

Java中List接口常见的实现类

目录 ArrayList实现类 数据存储 构造器 成员方法&#xff1a;CRUD Vector实现类 数据存储 构造器方法 成员方法 LinkedList实现类 数据存储 构造器方法 成员方法CRUD List总结 ArrayList&#xff1a;数组实现&#xff0c;随机访问速度快&#xff0c;增删慢&#x…...

SPI通信

SPI通信&#xff1a; 四根通信线&#xff1a;SCK,MOSI,MISO,SS&#xff08;从机选择线&#xff09; 同步时钟&#xff0c;全双工 支持总线挂载多个设备&#xff0c;一主多从 SPI相对IIC传输更快&#xff0c;最简单&#xff0c;最快速 SPI没有接收和应答机制&#xff0c;发送就发…...

【动态规划】【数论】【区间合并】3041. 修改数组后最大化数组中的连续元素数目

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 数论 区间合并 LeetCode3041. 修改数组后最大化数组中的连续元素数目 给你一个下标从 0 开始只包含 正 整数的数组 nums 。 一开始&#xff0c;你可以将数组中 任意数量 元素增加 至多 1 。 修改后&#xff0c;你可以从…...