尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

记录一次USB虚拟网络问题排查

记录一次USB虚拟网络问题排查
📅 发布时间:2026/6/20 5:35:30

背景介绍

项目是用yocto构建的,在升级kernel及yocto后(见https://www.cnblogs.com/ma-yangbiao/p/19149251), 发现某些功能不能正常工作。

问题介绍

目标机是某个不常用的x86平台,该x86 盒子通过USB连接MDM9150, 在该x86盒子上跑某个应用程序过程中,发现没有像预期一样建立和初始化USB虚拟网口custom_usb0。

调试

由于qxdm log在该目标机上受限。加入一些文本打印,重新编译运行,进一步调试发现是因为我们一个管理网络的服务ioctl返回错误,这个ioctl是自己客制化的驱动代码里负责处理的,

于是把相关的驱动编译成模块然后手动加载进内核,其中现象如下

$ sudo insmod ./custom_usb.ko

insmod: ERROR: could not insert module custom_usb.ko: Unknown symbol in module

$ dmesg | tail

[ 183.497776] custom_usb: Unknown symbol usbnet_suspend (err -2)

[ 183.497778] custom_usb: Unknown symbol usbnet_start_xmit (err -2)

[ 183.497793] custom_usb: Unknown symbol usbnet_stop (err -2)

[ 183.497797] custom_usb: Unknown symbol usbnet_disconnect (err -2)

[ 183.497801] custom_usb: Unknown symbol usbnet_probe (err -2)

[ 183.497804] custom_usb: Unknown symbol usbnet_resume (err -2)

这几个符号都来自linux kernel 驱动代码,具体在kernel/drivers/net/usb/usbnet.c,由CONFIG_USB_USBNET决定是否编译,但是在我的自己的defconfig中CONFIG_USB_USBNET已经被显示设置为y了。

于是在我的defconfig把CONFIG_USB_USBNET=m,重新编译后待会手动加载看看是不是报错,

同时该文件中有几处打印用的netdev_dbg,为了方便调试有2种方法运行时看到打印信息,

把netdev_dgb改成netdev_warn

改CONFIG_DYNAMIC_DEBUG=y,这是为了打开编译时动态打印开关,运行时还需要打开运行时调试开关:echo 'file drivers/net/usb/usbnet.c +p' > /sys/kernel/debug/dynamic_debug/control,这样即使是netdev_dbg也能打印到dmesg

我选择方法1,

再次编译完执行insmod usbnet.ko发现没有错误,再手动insmod custom_usb.ko也没有错误.

说明代码没问题,回过头来在usbnet.c-> usbnet_init()里加一句打印 pr_err("usbnet_init called\n");

我的defconfig里再设置CONFIG_USB_USBNET=y,重新编译更新,再次重启发现没有这句打印, 也就是说这个usbnet压根没有自动加载。

于是检查最终的defconfig检查一下,发现最终的.config里CONFIG_USB_USBNET=m

经过检查我的kernel recipe .bbapend代码,有这么一段值得怀疑

do_preconfigure_prepend () {

cat ${WORKDIR}/custom/defconfig >> ${WORKDIR}/defconfig

}

如果我更新后,还有别的部分更新那就会覆盖我的配置。

于是尝试删除上述这三行,同时加入这2行,

SRC_URI += "file://custom/defconfig.cfg"

KERNEL_FEATURES += " custom/defconfig.cfg"

再次编译,查看.config.还是不起作用CONFIG_USB_USBNET=m.

阅读源码,Kconfig并没有提及CONFIG_USB_USBNET是否有依赖项,查看代码CONFIG_USB_USBNET实际是属于CONFIG_USB_NET_DRIVERS的一个子模块,所以尝试也配置

CONFIG_USB_NET_DRIVERS=y

CONFIG_DYNAMIC_DEBUG=y

再次编译,这次可以看到最终的.config里已经成功使能CONFIG_DYNAMIC_DEBUG=y了。说明kernel升级后这些配置项与旧版本里的配置不再一样。

再重新烧image,重新尝试,在解决了其它问题后功能终于正常。

总结

yocto 的内核配置流程是:从 BSP 提供的 defconfig 开始,按顺序合并 KERNEL_FEATURES 和 SRC_URI 中的 .cfg 片段, 运行 merge_config.sh + olddefconfig 生成最终 .config。

kernel升级,伴随的一些配置的依赖项可能会发生变化,需要仔细确认。比如在我们这个case里,CONFIG_USB_USBNET依赖发生了变化,旧kernel里并不依赖CONFIG_USB_NET_DRIVERS,但新kernel版本依赖它。

usbnet的功能

最后分享一下,这次debug过程中加深了对usbnet的功能的认识,

usbnet.c 是一个通用的 USB 网络驱动核心,定义了一个结构体 struct usbnet,它包含struct net_device, struct usb_interface等指针,就像胶水一样把usb操作与网络的操作net_device联系在一起

它实现了一个“USB 网络设备”的抽象:负责处理 USB 传输、数据包队列,以及与内核的 net_device 的集成交互。通过usb虚拟网口收发数据等通用逻辑放在这里。

它被许多小型驱动程序共享:例如 cdc_ether、asix、r8152、rmnet_usb 等都依赖于 usbnet 作为基础,这些特定厂商的驱动只需重写/写少量部分即可。它将通用逻辑与硬件特性分离:核心部分负责收发(TX/RX)管理等通用逻辑,而其它特定的驱动则通过重写钩子函数来实现设备特定的行为。

它还导出了一些辅助函数,供其他驱动调用。

最终效果是:当你插入一个 USB 网卡时,内核可以将其识别为 usb0;而通过少量的驱动特定代码,也可以显示为例如 rmnet_usb0 等。

具体解读

模块初始化/退出

usbnet_init():注册通用的 USB 驱动框架,准备好供子驱动调用。

usbnet_exit():注销驱动,释放资源。

设备探测与移除

usbnet_probe():当匹配的 USB 设备插入时调用,分配并初始化 struct usbnet 和 struct net_device。

usbnet_disconnect():设备拔出时清理资源。

网络设备操作

usbnet_open() / usbnet_stop():启动或停止接口,提交/取消接收 URB。

usbnet_start_xmit():把上层网络栈传下来的数据包封装成 URB,提交给 USB core。

usbnet_change_mtu()、usbnet_set_mac_address():常见的 net_device 操作。

数据收发路径

发送 (TX):start_xmit() → 构造 URB → usb_submit_urb() → 设备。

接收 (RX):URB 完成回调 → rx_complete() → 调用 netif_rx() 把包交给内核协议栈。

提供 rx_fixup() / tx_fixup() 钩子,供子驱动修正报文格式。

电源管理与错误恢复

处理 USB suspend/resume。提供 usbnet_tx_timeout() watchdog,避免传输卡死。

相关新闻

  • 485报文订阅服务
  • 【URP】Unity[后处理]颜色曲线ColorCurves
  • 中小诊所系统通常具备哪些功能?

最新新闻

  • XXPermissions:Android权限管理的终极解决方案与实战指南
  • MongoDB 连接的幕后故事
  • 为什么Binding是Go Web开发者的必备工具:无反射数据绑定详解
  • 贝叶斯优化在低能电子衍射表面结构分析中的应用
  • Mobaxterm中文版终极指南:如何用一款工具解决所有远程管理难题?
  • 低代码表单在企业流程管理中的应用场景

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号