c - 如何从/dev/xxxx读取数据?

标签 c linux-kernel linux-device-driver kernel-module

我最近正在开发一个在内核模块上读写数据的项目。我创建了一个 C 语言应用程序来读取和写入内核模块上的数据(字符数据)。我也可以使用

写入数据
echo hello > /dev/xxxx

如何在没有 C 语言代码的情况下读回我存储的数据?我可以使用这样的东西吗?

cat /dev/xxxx

当我使用这个时,我遇到了段错误。

read value </dev/xxxx

当我使用它时,dmesg 显示内核模块永远保持运行读取函数。

[root@zzzz TUNNEL_EXCHANGE]# echo hello > /dev/xxxx 
yyyy: device opened
yyyy: call for write
yyyy: Value written
yyyy: device released
[root@zzzz TUNNEL_EXCHANGE]# line=$(head -n 1 /dev/xxxx)
yyyy: device opened
Unable to handle kernel paging request at virtual address af001000
pgd = eead0000
[af001000] *pgd=3e8eb811, *pte=00000000, *ppte=00000000
Internal error: Oops - BUG: 7 [#1] PREEMPT SMP ARM
Modules linked in: xxxx_driver(PO)
CPU: 0 PID: 927 Comm: head Tainted: P           O    4.6.0-xilinx #1
Hardware name: Xilinx Zynq Platform
task: eeb03600 ti: ee940000 task.ti: ee940000
PC is at __copy_to_user_std+0x4c/0x3c4
LR is at 0x0
pc : [<b02c051c>]    lr : [<00000000>]    psr: 20070013
sp : ee941ecc  ip : 00000000  fp : 00000000
r10: 00000000  r9 : ee940000  r8 : 00000000
r7 : 00000000  r6 : 00000000  r5 : 00000000  r4 : 00000000
r3 : 00000000  r2 : 000015c0  r1 : af001000  r0 : aeeb2524
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: 3ead006a  DAC: 00000055
Process head (pid: 927, stack limit = 0xee940210)
Stack: (0xee941ecc to 0xee942000)
1ec0:                            ee941f88 00000051 00002000 b0106f04 aeeb1b64
1ee0: 00002000 00000000 00002000 af000140 aeeb1b64 af0000ec ee941f88 b01c3544
1f00: aeeb3fbd 0002817d 00000000 b0101274 00001000 00000000 00000000 00001000
1f20: 00000003 ee9be680 ef31e700 00000003 00000000 ef31e740 00000000 ee932d80
1f40: ee941f88 00002000 aeeb1b64 aeeb1b64 ee932d80 ee941f88 00002000 b01c411c
1f60: ee932d80 aeeb1b64 00002000 ee932d80 ee932d80 aeeb1b64 00002000 b0106f04
1f80: ee940000 b01c4cac 00000000 00000000 00002000 00002000 7fffe000 00000001
1fa0: 00000003 b0106d40 00002000 7fffe000 00000003 aeeb1b64 00002000 77a94100
1fc0: 00002000 7fffe000 00000001 00000003 00000003 aeeb3fbd 0002817d 00000000
1fe0: 00000000 aeeb1ad4 000150a8 a6f32890 60070010 00000003 00000000 00000000
[<b02c051c>] (__copy_to_user_std) from [<af000140>] (xxxx_read+0x54/0x8c [xxxx_driver])
[<af000140>] (xxxx_read [xxxx_driver]) from [<b01c3544>] (__vfs_read+0x1c/0xcc)
[<b01c3544>] (__vfs_read) from [<b01c411c>] (vfs_read+0x84/0xec)
[<b01c411c>] (vfs_read) from [<b01c4cac>] (SyS_read+0x3c/0x74)
[<b01c4cac>] (SyS_read) from [<b0106d40>] (ret_fast_syscall+0x0/0x3c)
Code: ba000002 f5d1f03c f5d1f05c f5d1f07c (e8b151f8) 
---[ end trace c5d8c90d390bee96 ]---
yyyy: device released
[root@zzzz TUNNEL_EXCHANGE]# echo  $line 

[root@zzzz TUNNEL_EXCHANGE]# 

这是内核驱动代码读取函数

static ssize_t xxxx_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
    printk(KERN_ALERT "xxxx: call for read\n");
    //if(xxxx_str != NULL && count != 0 && count < TEXTLENGTH ){
            if(copy_to_user(buf, xxxx_str, count))
                    return -EINVAL; 
        *ppos = count;
        printk(KERN_ALERT "xxxx: Value Read\n");
        return count;
    //}
    //printk(KERN_ALERT "xxxx: Value Not Read\n");
    //return 1;
}

这可以很好地与 C 语言的打开、写入、读取、关闭系统调用配合使用。

最佳答案

您的 read 函数实现已损坏:

  1. 您不会检查 count 是否太大。在这种情况下,您应该只复制可用的字节数。
  2. 您不使用当前文件位置的值,这在多次读取的情况下会产生奇怪的结果。

由于上述组合,您的函数也无法发出文件结束信号(当没有更多数据时返回 0)。因此,如果您的代码没有由于#1而崩溃,它很可能会永远循环。

关于c - 如何从/dev/xxxx读取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44748934/

相关文章:

c - 这个 rwlock 实现有什么问题吗?

linux - 为什么系统调用使用不同的堆栈?

linux - obj-m : in Linux device driver Makefile是什么意思

cdev初始化为linux设备驱动: what is the difference between the two approaces?

c - 服务器意外关闭网络连接

c++ - 比较运算符的类似数学的链接 - 如 "if ( (5<j<=1) )"

c - 是否将数组转换为 C 中可移植的同构结构?

linux-kernel - 如何从内核模块访问(打开/读取/等)/dev 设备?

c - 操作系统架构: Kernel and Standard Library interoperability

linux-kernel - register_wide_hw_breakpoint 持续触发处理程序回调