Openwrt与Qemu联袂:打造高效内核源码调试环境

1. 为什么选择OpenWrt + Qemu进行内核调试?

如果你和我一样,是个喜欢折腾底层、想搞清楚Linux内核到底怎么工作的开发者,那你肯定也遇到过调试的难题。直接在物理机上调试内核?风险太高,一不小心系统就挂了。用虚拟机装个通用发行版?总觉得和嵌入式环境隔了一层,配置起来也麻烦。我之前试过用Buildroot配合Qemu,虽然能跑起来,但每次想往里加个自己的小应用或者内核模块,都得折腾半天,特别是内核模块,在Buildroot的菜单里找对应的配置项就像大海捞针。

后来我把目光投向了OpenWrt。这家伙在嵌入式领域可是大名鼎鼎,它不仅仅是一个路由器固件,更是一个高度模块化、定制化极强的Linux发行版。它的构建系统对“添加自定义软件包”和“内核模块”的支持,简直可以用“贴心”来形容。你想加什么,基本上在make menuconfig的图形界面里勾勾选选就能搞定,Makefile框架帮你处理了绝大部分复杂的依赖和编译流程。这正好切中了我进行内核源码级调试的核心痛点:我需要一个能快速迭代、方便修改和验证的仿真环境。

而Qemu,就是为这个环境提供“肉身”的绝佳伴侣。它是个纯软件的虚拟化利器,能模拟整个计算机系统,从CPU、内存到各种外设。最关键的是,它完美支持GDB调试。这意味着你可以让Qemu启动的虚拟机在某个断点停下来,然后通过GDB连接上去,单步跟踪内核代码的执行,查看内存和寄存器状态。这种“上帝视角”对于理解内核启动流程、驱动工作原理或者排查那些诡异的内核崩溃问题,是无可替代的。

所以,OpenWrt和Qemu联袂,一个提供了极度友好和灵活的定制化构建系统,另一个提供了完全可控、可深度调试的仿真沙盒。两者结合,就诞生了一个近乎完美的内核学习与调试环境。你可以在主机上舒适地编辑代码,用OpenWrt的框架编译,然后扔到Qemu里运行和调试,整个过程闭环,高效又安全。

2. 从零开始:搭建你的调试环境

好了,理论说完,咱们直接动手。我会带你走一遍完整的流程,把我踩过的坑和总结的技巧都分享出来,确保你能一次成功。

2.1 准备OpenWrt源码与编译环境

首先,我们需要一个“厨房”,也就是编译OpenWrt的主机环境。我用的是一台Ubuntu 22.04的机器,其实任何主流的Linux发行版都可以,主要确保工具链完整。

第一步,把OpenWrt的源码“请”下来。我推荐用官方主仓库,这样能获得最新的支持。

git clone https://github.com/openwrt/openwrt.git
cd openwrt

克隆完成后,先别急着编译。OpenWrt通过一个叫feeds的机制来管理额外的软件包集合,我们需要更新并安装它们。

./scripts/feeds update -a
./scripts/feeds install -a

接下来是安装编译依赖。这是最容易出错的一步,因为缺了哪个库,错误信息可能都不直接。下面这个命令清单比较全,涵盖了大部分情况,你可以一次性安装。

sudo apt-get update
sudo apt-get install -y build-essential ccache ecj fastjar file g++ gawk \
gettext git java-propose-classpath libelf-dev libncurses5-dev \
libncursesw5-dev libssl-dev python3 python3-distutils python3-setuptools \
python3-dev rsync subversion swig time unzip wget xsltproc zlib1g-dev

如果你的系统是CentOS或者Fedora,那就用yumdnf来安装类似的包组。核心就是编译器、库文件、解释器这些基础开发工具。

2.2 配置与编译针对Qemu的固件

环境齐备,现在来“定制菜单”。我们使用OpenWrt经典的配置界面:

make menuconfig

界面出来后,我们需要关注几个关键选择:

  1. Target System: 这是选择目标硬件架构。因为我们用Qemu模拟,选x86x86_64最通用。这里我们选 Target System -> x86
  2. Subtarget: 对于Qemu,选择 Generic 或者 Generic x86_64 就行。
  3. Target Images: 这里有个重要技巧!为了后续Qemu方便使用,我们最好生成一个直接的磁盘镜像文件,而不是压缩包。找到 Target Images -> GZip images按空格键取消选中(去掉前面的<*>)。这样最终会生成一个直接的.img文件。
  4. 添加基础工具: 为了调试方便,建议在 Utilities 栏目下,把 bashcoreutilsgdb(这是给虚拟机内用的)、stracetcpdump 等工具选上。Network 下可以选上 openssh-clientopenssh-server,方便网络登录。

配置完成后,保存退出。激动人心的编译时刻到了。第一次编译会下载很多工具链和软件包,时间比较长,可以去喝杯咖啡。

make -j$(nproc) V=s

这里的-j$(nproc)是用上你所有的CPU核心并行编译,加快速度。V=s是输出详细信息,如果出错,你能看到完整的错误日志,方便排查。编译成功后,在bin/targets/x86/64/目录下(具体路径根据你的选择略有不同),你会找到关键的产出物:openwrt-x86-64-combined-ext4.img。这就是我们要喂给Qemu的“硬盘”。

2.3 使用Qemu启动与配置OpenWrt虚拟机

有了镜像,就可以启动我们的虚拟“路由器”了。Qemu的命令参数看起来复杂,但拆解开来很好理解。

qemu-system-x86_64 \
  -m 512M \
  -smp 2 \
  -kernel ./bin/targets/x86/64/openwrt-x86-64-generic-kernel.bin \
  -drive file=./bin/targets/x86/64/openwrt-x86-64-combined-ext4.img,format=raw,index=0,media=disk \
  -append "root=/dev/sda console=ttyS0" \
  -nographic \
  -netdev user,id=wan,hostfwd=tcp:10022-:22 \
  -device virtio-net-pci,netdev=wan \
  -netdev user,id=lan \
  -device virtio-net-pci,netdev=lan \
  -s

我来解释一下这些参数:

  • -m 512M: 给虚拟机512MB内存,跑OpenWrt绰绰有余。
  • -smp 2: 模拟2个CPU核心。
  • -kernel-append: 这里我们直接指定了编译出的内核文件(-kernel)和内核启动参数(-append),告诉内核根文件系统在第一个磁盘(/dev/sda)上,控制台输出到串口(ttyS0)。
  • -nographic: 这个参数非常关键!它表示不使用图形窗口,所有输出重定向到当前终端,并且可以通过当前终端输入。这对于在服务器上运行或者喜欢纯命令行操作的人来说是首选,也方便我们重定向日志。
  • -netdev-device: 我们创建了两个用户模式的网络设备(wan和lan)。hostfwd=tcp:10022-:22 是一个魔法参数,它将主机(你的物理机)的10022端口,转发到虚拟机的22号(SSH)端口。这样,你可以在主机上执行 ssh -p 10022 root@localhost 就能登录进虚拟机,比用串口方便太多。
  • 最重要的 -s: 这个参数是调试的钥匙。它告诉Qemu在1234端口开启一个GDB调试服务器,等待连接。

启动后,虚拟机就开始跑起来了。第一次启动可能会在控制台看到内核日志刷刷地过,最后出现OpenWrt的登录提示。默认密码为空,直接回车就能以root身份进入。你可以通过前面设置的端口映射,用SSH登录进去,操作会更舒服。

3. 实战:利用GDB进行内核源码级调试

环境跑起来了,现在进入最核心的环节——调试。我们目标是能够像调试普通程序一样,单步执行内核代码。

3.1 准备带调试信息的内核

要让GDB能显示源码和符号,我们需要确保编译的内核包含调试信息。在OpenWrt的 make menuconfig 中,需要开启内核的调试选项: 进入 Global build settings -> [*] Build packages with debugging symbols。 更重要的是内核本身的调试符号,这通常在编译时自动包含在vmlinux文件中。OpenWrt编译后,在 build_dir/target-xxxx/linux-x86_64/ 目录下会有一个叫 vmlinux 的文件(注意不是vmlinux.bin),这个就是带有完整调试信息的ELF格式内核文件。记下它的路径。

3.2 连接GDB与设置断点

首先,在你主机的另一个终端里,启动GDB,并加载带调试信息的内核文件。

cd /path/to/your/openwrt
gdb ./build_dir/target-x86_64_musl/linux-x86_64/vmlinux

GDB启动后,连接到正在运行的Qemu虚拟机(它正在1234端口等待)。

(gdb) target remote localhost:1234

如果连接成功,你会看到GDB打印出当前CPU暂停的位置(通常是一条hlt指令或类似内容)。现在,你可以像调试普通程序一样下断点了。比如,我想看看do_fork函数(或者新版内核的kernel_clone)是怎么被调用的:

(gdb) b do_fork
Breakpoint 1 at 0xffffffff8108a7a0: file kernel/fork.c, line 2323.
(gdb) c
Continuing.

c是继续执行。此时,虚拟机里的系统会继续运行。当有进程创建时,就会触发这个断点,虚拟机会完全暂停,控制权回到GDB。这时你可以:

  • bt: 查看调用栈,看看是谁调用了do_fork
  • list: 查看断点附近的源代码。
  • print 变量名: 查看变量的值。
  • info registers: 查看寄存器状态。
  • s / n: 单步步入或步过。

这种一切尽在掌握的感觉,对于理解内核动态行为至关重要。你可以断在系统调用入口、中断处理函数、或者你自己写的驱动代码里。

3.3 调试自定义内核模块

调试自己写的内核模块稍微多一步。首先,你需要确保模块的源码在编译时也加了-g选项。在OpenWrt的模块Makefile里,通常TARGET_CFLAGS会包含调试信息。 假设你的模块叫my_module.ko。在虚拟机里,用insmod加载它。然后,在主机GDB中,你需要手动添加这个模块的符号文件。

(gdb) add-symbol-file /path/to/your/module.ko 0xffffffffc0000000

这里的0xffffffffc0000000是模块加载的基地址,这个地址需要你在虚拟机里通过cat /proc/moduleslsmod查看my_module模块信息来获取。加载符号后,你就可以在模块的函数里下断点了。

4. 扩展:在OpenWrt中添加自定义应用与内核模块

OpenWrt构建系统的精髓就在于“自定义”。下面我以添加一个简单的“Hello World”应用和一个同样简单的内核模块为例,展示其便捷性。

4.1 添加一个用户态应用程序

在OpenWrt的package目录下,创建一个属于你的目录,比如package/mypackages/hello。这个目录里需要两个核心文件:Makefile和存放源码的src目录。 package/mypackages/hello/Makefile 内容大致如下:

include $(TOPDIR)/rules.mk

PKG_NAME:=hello
PKG_VERSION:=1.0
PKG_RELEASE:=1

PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

define Package/hello
  SECTION:=utils
  CATEGORY:=Utilities
  TITLE:=A simple hello world program
  DEPENDS:=
endef

define Package/hello/description
  This is a simple hello world program for OpenWrt.
endef

define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
    $(MAKE) -C $(PKG_BUILD_DIR) \
        $(TARGET_CONFIGURE_OPTS) \
        CFLAGS="$(TARGET_CFLAGS)"
endef

define Package/hello/install
    $(INSTALL_DIR) $(1)/usr/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/hello $(1)/usr/bin/
endef

$(eval $(call BuildPackage,hello))

package/mypackages/hello/src/目录下,就是你的C代码hello.c和一个简单的Makefilehello.c:

#include <stdio.h>
int main() {
    printf("Hello from OpenWrt!\n");
    return 0;
}

src/Makefile:

hello: hello.o
    $(CC) $(LDFLAGS) hello.o -o $@
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
clean:
    rm -f *.o hello

完成后,回到OpenWrt根目录,执行make menuconfig,你会在 Utilities -> hello 找到它,选中编译即可。编译出的ipk包会自动集成到固件里,或者你可以单独安装。

4.2 添加一个简单的内核模块

添加内核模块OpenWrt也做了很好的封装。通常不建议直接修改内核树,而是以“内核补丁包”的形式添加。更简单的一种方式是,利用OpenWrt对“内核模块包”的支持。 在package/kernel目录下创建一个新目录,比如mymodule。其Makefile如下:

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=mymodule
PKG_VERSION:=1.0
PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

define KernelPackage/mymodule
  SUBMENU:=Other modules
  TITLE:=My simple test kernel module
  FILES:=$(PKG_BUILD_DIR)/mymodule.ko
  AUTOLOAD:=$(call AutoProbe,mymodule)
  KCONFIG:=
endef

define KernelPackage/mymodule/description
  This is a simple test kernel module.
endef

define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
    $(MAKE) -C "$(LINUX_DIR)" \
        M="$(PKG_BUILD_DIR)" \
        modules
endef

$(eval $(call KernelPackage,mymodule))

同样,在src目录放置你的内核模块源码mymodule.c和对应的Makefile。这个Makefile就简单指向内核构建系统: src/Makefile:

obj-m += mymodule.o

配置时,在 make menuconfigKernel modules -> Other modules 里就能找到 kmod-mymodule,选中它。编译后,这个模块就会自动打包,并在系统启动时尝试加载(因为AUTOLOAD指定了AutoProbe)。

通过这种方式,你完全不需要手动去修改Linux内核的Kconfig和Makefile,所有工作都在OpenWrt的包管理框架内完成,干净又省心。当你需要调试这个模块时,就回到第三章的方法,用GDB加载其符号进行调试即可。

整个流程走下来,你会发现OpenWrt+Qemu这个组合,把嵌入式Linux内核开发的门槛降低了不少。它给了你一个安全的沙盒、一套高效的构建工具、和一个强大的调试器。剩下的,就是你探索内核奥秘的好奇心和耐心了。我至今还记得第一次通过GDB单步走进schedule()函数时的那种兴奋感,仿佛打开了新世界的大门。希望这个环境也能帮你打开那扇门。

内容概要:本文档名为《赵家湾学校后大门一百三十六栋.txt》,实则是一份综合性科研仿真资源索引,集中展示了多个技术领域的Matlab/SimulinkPython代码实现项目。内容涵盖风光互补制氢合成氨系统容量-调度优化、微电网能量管理、无人机三维路径规划、图像分割、信号处理、电力系统建模、模型预测控制(MPC)、深度学习预测模型(如LSTM、Transformer)、联邦学习、强化学习应用等多个前沿方向。文档不仅列出具体研究题目和算法模型,还整合了智能优化算法(如PSO、GWO、DBO等)、路径规划、车间调度、通信优化、雷达跟踪、元胞自动机模拟等通用技术模块,并附有网盘链接提供完整代码仿真模型下载,旨在为科研人员提供可复现的技术支持开发参考。; 适合人群:具备一定编程基础,从事电气工程、自动化、计算机科学、人工智能、控制工程、能源系统等相关领域的研究生、科研人员及工程技术开发者。; 使用场景及目标:①辅助高水平学术论文复现科研项目开发;②为硕士/博士论文、课程设计、学科竞赛提供算法实现仿真建模支持;③提升在新能源并网、智能控制、路径规划、负荷预测、故障诊断等领域的工程实践创新能力。; 阅读建议:此文档为资源导航型材料,建议结合个人研究方向筛选对应主题,通过提供的百度网盘链接获取完整代码包,并配合相关文献进行仿真实验参数调试,以实现高效复用、二次开发技术创新。
内容概要:本文深入解析了AI Agent(智能体)的技术原理系统架构,阐述其如何通过“思考-行动-观察”的闭环循环,使大语言模型(LLM)从被动应答的对话系统进化为能主动完成复杂任务的智能实体。文章详细介绍了Agent四大核心模块:作为决策中枢的LLM(大脑)、实现外部交互的工具调用(双手)、支持状态延续的记忆模块(记忆),以及驱动自主执行的规划协调机制(协调)。同时对比了Agent传统聊天机器人在任务规划、工具使用、记忆能力和执行闭环等方面的本质差异,并探讨了从单智能体到多智能体系统的架构演进趋势,强调专业分工对处理复杂任务的重要性。最后,文章分析了Agent模式预设工作流模式的应用权衡,指出前者适用于灵活探索类任务,后者更适合确定性高的固定流程。; 适合人群:对人工智能、大模型应用开发感兴趣的技术人员、产品经理及研究人员,尤其适合具备一定AI基础知识、希望深入了解Agent系统设计的专业人士; 使用场景及目标:①理解AI Agent的核心架构关键技术组件;②掌握ReAct等主流执行范式;③区分Agent传统聊天机器人的能力边界;④判断在实际业务中应采用Agent模式还是工作流模式; 阅读建议:本文理论性强且结构清晰,建议结合实际Agent案例(如AutoGPT、LangChain应用)进行对照学习,重点关注各模块间的协同机制设计权衡,以深化对Agent系统级思维的理解。
内容概要:本文针对三相并网逆变器在瞬态过程中的全局最优控制问题,提出一种基于有限字符集预测控制(FCS-MPC)的渐进式调控策略,旨在实现从电流畸变抑制到功率无差拍响应的平滑过渡。通过构建电流功率双模态预测控制框架,结合Simulink仿真Matlab代码实现,系统分析了有限控制集对系统动态响应、谐波含量及功率调节性能的影响机理,深入探讨了预测模型构建、代价函数设计控制参数优化的关键技术路径,验证了该策略在提升并网电能质量、增强动态响应能力和实现多目标协同控制方面的优越性可行性; 适合人群:具备电力电子、自动控制理论基础,熟悉Matlab/Simulink仿真环境,从事新能源发电并网、逆变器先进控制策略研究等相关领域的研究生、科研人员及工程技术人员; 使用场景及目标:①深入研究有限集模型预测控制在三相并网系统中的理论应用;②掌握电流功率双模态预测控制策略的设计方法实现流程;③实现高动态性能、低谐波畸变功率快速无差拍响应的综合控制目标; 阅读建议:建议结合文中提供的Matlab代码Simulink仿真模型进行复现实验,重点剖析预测时域设定、代价函数权重配置及开关状态枚举策略对系统性能的影响,以全面理解FCS-MPC的核心原理及其在工程实践中的优化技巧。
内容概要:本文系统阐述了多层感知机(MLP)神经网络的底层原理、从零手写代码实现、工程化框架落地及超参数优化的完整体系。内容涵盖MLP的理论基础、前向传播反向传播的数学推导、激活函数损失函数的选择、NumPy原生实现PyTorch/TensorFlow工业级封装,并深入解析了网络结构、训练优化、正则化等超参数的系统化调参策略。通过构建“数学原理→代码实现→调参优化→故障排查→工业实战”的闭环体系,提供可复用的标准化模型开发流程,结合分类回归实战案例,全面指导模型评估、可视化部署落地。; 适合人群:具备一定Python和机器学习基础,从事AI研发、数据科学、工程建模的1-5年经验技术人员,以及高校科研人员企业AI落地团队。; 使用场景及目标:①掌握MLP神经网络的数学本质代码实现机制;②系统学习超参数调优策略,解决过拟合、欠拟合、梯度异常等常见问题;③实现从学术理解到工业级模型部署的全流程落地;④提升在结构化数据建模任务中的模型性能鲁棒性。; 阅读建议:建议结合文中提供的NumPyPyTorch代码边学边练,重点理解反向传播推导调参逻辑,对照实战案例进行调试优化,建议按章节顺序学习,尤其重视第5章超参体系第9章故障排查,以建立系统性调参思维问题解决能力。
内容概要:本文研究了基于UPML的三维有限差分时域法(3D FDTD)在微带低通滤波器分析中的应用,通过Matlab代码实现对平面微带电路电磁特性的精确仿真。文章系统阐述了3D FDTD方法的核心原理,包括麦克斯韦方程的离散化处理、Yee网格的空间配置、时间步进迭代算法以及数值稳定性条件(如Courant-Friedrichs-Lewy条件)。重点介绍了UPML(单轴各向异性完全匹配层)吸收边界条件的数学建模编程实现,有效抑制了计算域边界的非物理反射,提升了高频电磁仿真精度。通过建立微带低通滤波器的三维几何模型,进行精细网格剖分,并施加端口激励,计算获得了S参数曲线、电磁场分布云图等关键结果,验证了该方法在高频电路设计中对信号完整性电磁兼容性分析的有效性高精度优势。; 适合人群:具备电磁场微波技术理论基础、熟悉Matlab编程,从事高频/高速电路设计、天线工程、PCB信号完整性分析及相关领域的研究生、科研人员及电子系统研发工程师。; 使用场景及目标:①掌握3D FDTD方法在平面微波器件仿真中的全流程实现技术;②深入理解UPML边界条件的物理机制及其在减少截断误差中的关键作用;③为微带滤波器、功率分配器、耦合器等无源器件及高速互连结构的设计优化提供可靠的数值仿真手段; 阅读建议:建议读者结合所提供的Matlab代码逐行调试,重点关注差分格式的离散过程、UPML区域的参数设置场量更新逻辑,并尝试调整介质基板参数或滤波器拓扑结构,观察S参数和场分布的变化,以深化对电磁波传播特性、谐振行为及边界吸收机制的理解。
内容概要:本文聚焦于有源中点箝位(ANPC)三电平并网逆变器的高性能控制策略研究,针对传统逆变器在电网不平衡、谐波扰动等复杂工况下存在的谐波含量高、动态响应慢、稳定性差等问题,提出了一种融合双极性倍频脉宽调制(DPWMA)、正负序分离锁相技术电网电压前馈控制的一体化控制方案。通过深入分析ANPC三电平拓扑的结构优势,结合DPWMA调制策略优化开关动作以改善输出波形质量,利用正负序分离锁相实现电网相位的精确跟踪,并引入电网电压前馈有效抑制外部扰动对系统的影响,从而全面提升并网电能质量系统鲁棒性。研究在Simulink环境中搭建了完整的仿真模型,对稳态运行、电网不平衡及动态切换等多种工况进行了验证,结果表明该控制策略能显著降低电流谐波、提高锁相精度和动态响应速度,具备良好的工程应用前景。此外,文档还整合了大量基于Matlab/Simulink的科研资源,覆盖微电网优化、电动汽车接入、风光储协同调度、路径规划、神经网络预测等多个前沿方向。; 适合人群:具备电力电子、自动控制或新能源系统背景,从事相关科研工作的研究生、工程师及高校教师,尤其适合有一定Matlab/Simulink仿真基础的研发人员。; 使用场景及目标:①用于新能源并网逆变器控制系统的设计优化;②支撑高水平论文复现、科研项目开发工程仿真验证;③为电力系统、智能控制、无人机路径规划等领域的算法研究提供代码参考和技术路线借鉴。; 阅读建议:建议结合文中提供的仿真模型代码资源,按照目录结构系统学习控制策略设计逻辑,并通过实际仿真实验加深对DPWMA调制、正负序分离、前馈补偿等核心技术的理解掌握。
代码下载地址: https://pan.quark.cn/s/1065f510e03d Hackerrank是一个国际性的技术人才招聘平台,它借助一系列的编程挑战和练习活动,旨在帮助求职者提升编程能力并为职业发展做好准备。本解析涵盖了多种编程语言和算法的核心内容,以下将从所提供的文档资料中归纳出相关学习要点。 ## 学习要点总结 ### 关于Hackerrank - Hackerrank是一个面向程序开发者的在线编程学习平台。 - 通过攻克具有难度的编程任务,能够促进程序员精通不同的编程语言和算法技术。 - 该平台既适合准备进入北美就业市场的求职者,也适合在中国寻求工作机会的人群。 ### 编程语言应用 - C++11:这是一种C++编程语言的新版本,引入了多项增强功能。 - Scala:一种支持多种编程范式的语言,融合了面向对象和函数式编程的特点。 ### 算法数据结构 - 该资料包含了HackerRank上所有题目的解题方案。 - 适合读者深入研究和学习,有助于增强对数据结构和算法的理解程度。 ### 编程风格规范 - 采取较为简洁的代码编写方式,以快速完成功能实现为主。 - 递归方法优先于栈的使用,采用STL(标准模板库)而非自行构建数据结构。 - 不提倡防御式编程,不进行指针和参数的有效性检查。 ### 算法竞赛北美就业 - 对于初次接触ACM算法竞赛的新手,该书提供了理想的入门训练。 - 对于准备进入北美就业市场的求职者,书中内容同样具有参考价值。 ### 学习要点详细说明 接下来,将详细阐释书中涉及到的关于链表和排序的各个学习内容。 #### 链表 - **链表元素的输出**:设计一个函数来遍历并展示链表中所有节点的值。需要处理头节点为空的情况...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值