卸载驱动模块,内核崩溃排查调试记录

news/2025/10/12 18:42:52/文章来源:https://www.cnblogs.com/zhuliushun001/p/19137003

问题
在学习串口子系统,在卸载串口模块的时候,引起内核崩溃。具体的崩溃日志如下:
/mnt/uartdeep # rmmod virtual_uart.ko
[ 23.208560] /home/book/bsp/mcu/uartdeep/virtual_uart_ok/virtual_uart.c virtual_uart_exit 301
[ 23.217242] Before uart_remove_one_port
[ 23.221631] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 23.230235] pgd = 94598000
[ 23.233703] [00000000] *pgd=94800831, *pte=00000000, *ppte=00000000
[ 23.243278] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM
[ 23.249210] Modules linked in: virtual_uart(O-)
[ 23.253784] CPU: 0 PID: 110 Comm: rmmod Tainted: G O 4.1.15 #4
[ 23.260750] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[ 23.266939] task: 9426aac0 ti: 947ee000 task.ti: 947ee000
[ 23.272345] PC is at 0x0
[ 23.274894] LR is at uart_remove_one_port+0x130/0x150
[ 23.279954] pc : [<00000000>] lr : [<80354ad0>] psr: 200d0013
[ 23.279954] sp : 947efef8 ip : 16fcc000 fp : 00000000
[ 23.291435] r10: 00000000 r9 : 947ee000 r8 : 8000f604
[ 23.296667] r7 : 946fae9c r6 : 00000000 r5 : 946fae00 r4 : 94708010
[ 23.303201] r3 : 00000000 r2 : 00000000 r1 : 600d0013 r0 : 94708010
[ 23.309735] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 23.316876] Control: 10c53c7d Table: 9459806a DAC: 00000015
[ 23.322628] Process rmmod (pid: 110, stack limit = 0x947ee210)
[ 23.328466] Stack: (0x947efef8 to 0x947f0000)
[ 23.332830] fee0: 7f000ad8 7f00093c
[ 23.341017] ff00: 94102244 00000081 8000f604 7f000154 94102210 80385834 94102210 7f00093c
[ 23.349203] ff20: 94102244 80383c80 94102210 7f00093c 94102244 80384410 7f00093c 7e883bf0
[ 23.357392] ff40: 5f6c6175 803839e0 7f000904 7f0004ec 7f000980 800938e4 00001000 74726976
[ 23.365578] ff60: 5f6c6175 74726175 7e883c00 00000001 947ee000 00000000 76f23568 800d5eb8
[ 23.373766] ff80: 00100871 00000000 ffffffff 948025d8 76f23568 00027d38 76dcf5e4 00028a89
[ 23.381952] ffa0: 74726976 8000f480 00028a89 74726976 7e883bf0 00000880 00000000 7e883e88
[ 23.390138] ffc0: 00028a89 74726976 5f6c6175 00000081 00000002 00000000 76f23000 00000000
[ 23.398324] ffe0: 7e883be8 7e883bd8 000289d1 76e08ad2 800d0030 7e883bf0 97fbe821 97fbec21
[ 23.406535] [<80354ad0>] (uart_remove_one_port) from [<7f000154>] (virtual_uart_remove+0x64/0x9c [virtual_uart])
[ 23.416731] [<7f000154>] (virtual_uart_remove [virtual_uart]) from [<80385834>] (platform_drv_remove+0x18/0x30)
[ 23.426838] [<80385834>] (platform_drv_remove) from [<80383c80>] (__device_release_driver+0x70/0xe4)
[ 23.435987] [<80383c80>] (__device_release_driver) from [<80384410>] (driver_detach+0xac/0xb0)
[ 23.444612] [<80384410>] (driver_detach) from [<803839e0>] (bus_remove_driver+0x4c/0xa0)
[ 23.452720] [<803839e0>] (bus_remove_driver) from [<7f0004ec>] (virtual_uart_exit+0x30/0x40 [virtual_uart])
[ 23.462480] [<7f0004ec>] (virtual_uart_exit [virtual_uart]) from [<800938e4>] (SyS_delete_module+0x174/0x1b8)
[ 23.472413] [<800938e4>] (SyS_delete_module) from [<8000f480>] (ret_fast_syscall+0x0/0x3c)
[ 23.480692] Code: bad PC value
[ 23.487156] ---[ end trace f7196ca02fb58b98 ]---
Segmentation fault
/mnt/uartdeep # [ 85.962528] random: nonblocking pool is initialized
由上述日志来看,是由访问非法地址(0地址),造成内核崩溃。而且崩溃的函数是uart_remove_one_port,具体的偏移是0x130
uart_remove_one_port具体实现
该函数的具体承载在文件:drivers/tty/serial/serial_core.c
具体的实现是:
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
{
struct uart_state *state = drv->state + uport->line;
struct tty_port *port = &state->port;
struct tty_struct *tty;
int ret = 0;

    BUG_ON(in_interrupt());if (state->uart_port != uport)dev_alert(uport->dev, "Removing wrong port: %p != %p\n",state->uart_port, uport);mutex_lock(&port_mutex);/** Mark the port "dead" - this prevents any opens from* succeeding while we shut down the port.*/mutex_lock(&port->mutex);if (!state->uart_port) {mutex_unlock(&port->mutex);ret = -EINVAL;goto out;}uport->flags |= UPF_DEAD;mutex_unlock(&port->mutex);/** Remove the devices from the tty layer*/tty_unregister_device(drv->tty_driver, uport->line);tty = tty_port_tty_get(port);if (tty) {tty_vhangup(port->tty);tty_kref_put(tty);}/** If the port is used as a console, unregister it*/if (uart_console(uport))unregister_console(uport->cons);/** Free the port IO and memory resources, if any.*/if (uport->type != PORT_UNKNOWN)uport->ops->release_port(uport);kfree(uport->tty_groups);/** Indicate that there isn't a port here anymore.*/uport->type = PORT_UNKNOWN;state->uart_port = NULL;

out:
mutex_unlock(&port_mutex);

    return ret;

}

dump日志文件提示,出错点在偏移为0x130(304)字节处
具体的指令与字符换算关系如下(32位系统):
1条c语言指令(210条汇编指令-840字节)
简单语句:2~4条指令 (8~16字节)
函数调用:48条指令(1632字节)
条件判断+分支:612条指令(2448字节)
累计之后,0x130的位置在uport->ops->release_port(uport)处。
该函数是在uart_port结构体的ops变量中。具体的情况如下:

static const struct uart_ops virt_pops = {
.tx_empty = virt_tx_empty,
.set_mctrl = virt_set_mctrl,
.get_mctrl = virt_get_mctrl,
.stop_tx = virt_stop_tx,
.start_tx = virt_start_tx,
.stop_rx = virt_stop_rx,
.startup = virt_startup,
.shutdown = virt_shutdown,
.set_termios = virt_set_termios,
.type = virt_type,
};

如上所示,在virt_pops中,没有release_port的实现。由此在调用uart_remove_one_port的时候,由于release_port为空,导致内核崩溃

修正
在virt_pops中,增加release_port的实现:具体如下所示:

static void virt_release_port(struct uart_port *port)
{
}
static const struct uart_ops virt_pops = {
.tx_empty = virt_tx_empty,
.set_mctrl = virt_set_mctrl,
.get_mctrl = virt_get_mctrl,
.stop_tx = virt_stop_tx,
.start_tx = virt_start_tx,
.stop_rx = virt_stop_rx,
.startup = virt_startup,
.shutdown = virt_shutdown,
.set_termios = virt_set_termios,
.type = virt_type,
.release_port = virt_release_port,
};

如上图所示,增加一个release_port的空实现。之前的问题得以解决。

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

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

相关文章

详细介绍:游戏引擎以及游戏开发

详细介绍:游戏引擎以及游戏开发pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…

springboot大学校园旧物捐赠网站(代码+数据库+LW) - 详解

springboot大学校园旧物捐赠网站(代码+数据库+LW) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

DropLoRA 论文浅读:通过动态子空间学习突破 LoRA 的性能瓶颈

DropLoRA是一项简单而深刻的工作。它通过一个极其轻量的动态剪枝模块,巧妙地解决了传统LoRA的静态子空间瓶颈问题。DropLoRA 论文浅读:通过动态子空间学习突破 LoRA 的性能瓶颈 一、研究背景 随着大规模语言模型(LL…

实用指南:PCB 半固化片:多层板制造的技术基石,猎板的场景化适配与质控逻辑

实用指南:PCB 半固化片:多层板制造的技术基石,猎板的场景化适配与质控逻辑pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-fam…

操作系统CPU和内核思维导图总结

操作系统CPU和内核思维导图总结 https://www.processon.com/view/link/60eef701e0b34d06fba955b4

defold游戏引擎与lua(teal)编程语言

最近有时在想:UE5很强大,但放不进浏览器;C++对个人游戏开发不友好(掉头发嘞~) Godot类似Blender,300MB编辑器大小,itch.io大量使用godot制作网页游戏。但是对WebGPU的支持遥遥无期,见 https://github.com/godo…

个人用云计算学习笔记 --16(DHCP 服务器) - 实践

个人用云计算学习笔记 --16(DHCP 服务器) - 实践2025-10-12 18:20 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displ…

03 数值类型拓展

数据类型拓展二进制0b八进制0十六进制0x 打印的结果默认为十进制浮点数拓展 #float 有限且离散,舍入误差,接近但不等于 #double #最好完全使用浮点数进行比较!!! #非要比较的话,有专用的类float f=0.1f; double d = 1…

python如何引用变量的名称

在Python中,引用变量的名称通常指的是动态地获取变量的标识符(即变量名)作为字符串。然而,需要注意的是,Python的变量更像是名字贴纸,贴在对象上,而不是容器。这种操作在一些特殊的场景下可能会用到,比如调试、…

Python GIL与No-GIL技术详解

Python的全局解释器锁(Global Interpreter Lock,简称GIL)是CPython解释器中最具争议和核心的设计之一。它深刻影响着Python的并发编程模型,也是许多开发者在使用Python进行多线程编程时遇到性能瓶颈的主要原因。Py…

题解:AT_abc288_h [ABC288Ex] A Nameless Counting Problem

用这个题总结一些互异容斥的 trick,参考了周子衡的论文。 题意:求出满足以下两个条件的长度为 \(N\) 的整数序列 \(A = (A_1, A_2, \ldots, A_N)\) 的个数,并对 \(998244353\) 取模。\(0 \leq A_1 \leq A_2 \leq \c…

2025 年 CBN 砂轮源头厂家最新推荐榜单:专业实力与客户满意度全景解析及选购指南

在航空航天零部件精密切削、电子芯片超精密研磨、汽车发动机关键部件加工等高端制造领域,CBN 砂轮作为核心耗材,其品质直接决定加工精度与生产效率。然而当前市场乱象频发:部分厂家技术薄弱,产品耐用性与精度稳定性…

JDK安装和卸载

新的快捷键 常用 shift+delete:永久删除文件 ctrl+shift+esc:打开任务管理器 alt+f4:关闭进程 ps:前阵子ow流行发一些图片表情和不同颜色字体的时候,很多人用来伪装系统提示引诱玩家按下alt+f4,结果真有人不知道…

Python定义一个User类的基本写法

定义一个类的基础语法如下: class User:# 初始化方法或者叫构造器def __init__(self, name, email):self.name = name # 实例变量name定义和赋值self.email = email # 实例变量email定义和赋值# 一个实例方法def gr…

Python飞快入门专业版(四十八):Python面向对象之多态:不同对象调用同一办法的不同达成(实战案例)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

10.12 CSP-S模拟30 改题记录

10.12 啥也不会场HZOJ 写在前面 貌似T3T4不太可改,遂先把前两题的写了。大概就是T1打表3小时没找到规律吧,喜提0pts。真是成也T1,败也T1。Dearest Darling My universe 亲爱的 亲爱的宇宙啊 날 데려가 줄래 能否带我…

ubuntu源码编译指定版本make

在Ubuntu系统中,源码编译是安装软件的一种高级方法,它允许用户针对特定的系统环境进行优化和定制。下面是一个针对Ubuntu平台从源码编译特定版本软件的详细流程,步骤旨在面向有一定Linux操作经验的用户。 准备工作安…

【LeetCode】274. H 指数

274. H 指数 题目 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指…

python之多态

多态 类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:class Person(object):def __init__(self, name, gender):self.name = name…