linux - 如何处理自写字符设备内核模块中的页域错误?

标签 linux module linux-kernel arm embedded-linux

你好

我正在使用 yocto 和 meta-atmel 为 Atmel 的 SAMA5D3x 平台生成自己的嵌入式 Linux。这包括一个自写的内核模块。这是一个非常简单的字符设备 (chrdev),它通过切换引脚来打开/关闭 LED。

当我将它构建到内核 4.1 中时,它运行良好。但是当迁移到内核 4.4 时,它在写入函数时因“页面域错误”而崩溃。

破解前的代码如下:

//! reads the commands from the i/o
static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
    char *  szDevice;
    int     deviceLen;
    char *  szPara;
    int     paraLen;
    char *  szValue;
    int     valueLen;
    size_t  remBytes;
    char *  szErrorStr;

    int devIndex, paraIndx;
    TBoardLed_State state;
    char tb[len+1];

    memcpy(tb, buff, len);
    tb[len] = 0;

    printk(KERN_INFO "%s: dev_write: %s (%i)\n", dSEK4Dev_indi, tb, (int) len);

错误打印是:

[  107.140000] Unhandled fault: page domain fault (0x01b) at 0x00101090
[  107.140000] pgd = d41a4000
[  107.140000] [00101090] *pgd=346e1831, *pte=3f5ba34f, *ppte=3f5ba83f
[  107.140000] Internal error: : 1b [#1] ARM
[  107.140000] Modules linked in: sek4matrixled(O) sek4comconfig(O) sek4boardled(O)
[  107.140000] CPU: 0 PID: 428 Comm: sh Tainted: G           O    4.4.19-linux4sam_5.4 #1
[  107.140000] Hardware name: Atmel SAMA5
[  107.140000] task: d45a0040 ti: d45b4000 task.ti: d45b4000
[  107.140000] PC is at memcpy+0x7c/0x330
[  107.140000] LR is at dev_write+0x2c/0x25c [sek4boardled]
[  107.140000] pc : [<c020effc>]    lr : [<bf0002f8>]    psr: 00020013
               sp : d45b5e74  ip : 0000000c  fp : d45b5efc
[  107.140000] r10: 00000000  r9 : d45b4000  r8 : c000f564
[  107.140000] r7 : d45b5f88  r6 : 00101090  r5 : 00000015  r4 : d45b5ea8
[  107.140000] r3 : 00000018  r2 : fffffff5  r1 : 00101090  r0 : d45b5ea8
[  107.140000] Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  107.140000] Control: 10c53c7d  Table: 341a4059  DAC: 00000051
[  107.140000] Process sh (pid: 428, stack limit = 0xd45b4208)
[  107.140000] Stack: (0xd45b5e74 to 0xd45b6000)
[  107.140000] 5e60:                                              00000015 00101090 d45b5f88
[  107.140000] 5e80: c000f564 d45b5ea8 d45b5ea8 bf0002f8 00000000 00000000 d45b4000 00000068
[  107.140000] 5ea0: d45b5ed8 befff3f0 befff3f0 c0219c8c d46e07fc d45b5fb0 d45a0040 d4650540
[  107.140000] 5ec0: 00000817 0010209c d4650574 00000055 00000800 c001674c 00000006 d457e1c0
[  107.140000] 5ee0: bf0002cc 00101090 d45b5f88 c000f564 d45b4000 00000000 00000000 c00a2ae8
[  107.140000] 5f00: b6f627cc 00006950 00007958 c000928c 00001000 00000000 00000000 00000000
[  107.140000] 5f20: 57dabaed 258d097f 57dabaed 258d097f 57dabaed 258d097f 000005e5 00000000
[  107.140000] 5f40: befff3f0 b6f62d58 b6f62d58 d457e1c0 00000015 00101090 d45b5f88 c000f564
[  107.140000] 5f60: d45b4000 c00a32b0 00000000 0fa00000 d457e1c0 d457e1c0 00101090 00000015
[  107.140000] 5f80: c000f564 c00a3ac8 00000000 00000000 b6fd16d0 00000015 00101090 b6f62d58
[  107.140000] 5fa0: 00000004 c000f3a0 00000015 00101090 00000001 00101090 00000015 00000000
[  107.140000] 5fc0: 00000015 00101090 b6f62d58 00000004 00000015 000ed124 00000001 00000000
[  107.140000] 5fe0: 00000000 befff954 b6e8fe6c b6ee8f80 60020010 00000001 00000000 00000000
[  107.140000] [<c020effc>] (memcpy) from [<bf0002f8>] (dev_write+0x2c/0x25c [sek4boardled])
[  107.140000] [<bf0002f8>] (dev_write [sek4boardled]) from [<c00a2ae8>] (__vfs_write+0x1c/0xd8)
[  107.140000] [<c00a2ae8>] (__vfs_write) from [<c00a32b0>] (vfs_write+0x90/0x16c)
[  107.140000] [<c00a32b0>] (vfs_write) from [<c00a3ac8>] (SyS_write+0x44/0x9c)
[  107.140000] [<c00a3ac8>] (SyS_write) from [<c000f3a0>] (ret_fast_syscall+0x0/0x3c)
[  107.140000] Code: ea000011 e320f000 e4913004 e4914004 (e4915004)
[  107.140000] ---[ end trace 2c62698a45a8d21d ]---

对我来说,我的模块不允许从用户空间读取数据。但是我不知道如何克服这个错误。

有什么想法吗?

最佳答案

正如 Tsyvarev 提到的,输入缓冲区需要通过 copy_from_user 从用户空间复制到内核空间。将 memcpy 替换为 copy_from_user 后,模块工作正常。

关于linux - 如何处理自写字符设备内核模块中的页域错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39515407/

相关文章:

linux - 为什么文件的 Date Modified 属性改变了,但我确定文件根本没有被修改

java - "Prism-ES2 Error : GL_VERSION (major.minor) = 1.4"可能是什么原因?

swift - 如何使 Swift 框架子模块真正私有(private)?

用户空间中的 linux 高分辨率计时器

linux - Android-studio 3.0-beta6 aapt 在 libc++.so 中失败

java - 如何使用 Java 代码为 iOS 创建钛移动模块?

Angular2 RC5 跨模块提供程序/扫描

linux-kernel - 从用户空间到内核空间的回调

linux-kernel - 系统调用 Hook 问题

c++ - 获取Boost Deadline_timer native 文件描述符