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

How to read data from /dev/xxxx?

我最近在做一个在内核模块上读写数据的项目。我创建了一个 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;
}

这与 open, write, read, close C 语言的系统调用配合得很好。

您的 read 功能实现已损坏:

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

综合上述情况,您的函数也无法发出文件结束信号(当没有更多数据时返回 0)。所以如果你的代码没有因为 #1 而崩溃,它很可能会永远循环下去。