为什么cat一次足够调用两次read()?

问题描述 投票:1回答:1

我是Linux内核模块的新手。我正在学习基于网络课程的char驱动程序模块。我有一个非常简单的模块,它创建一个/dev/chardevexample,我有一个问题需要我理解:

当我执行echo "hello4" > /dev/chardevexample时,我看到write仅按预期执行一次。但是,当我执行cat /dev/chardevexample时,我看到读取执行了[[two次。

我在代码和课程资料中都看到了这一点。所有数据都在第一个read()中返回,那么为什么cat再次调用它?

到目前为止,我所做的所有事情如下:

    [insmod chardev.ko加载我的模块
  1. echo "hello4" > /dev/chardevexample。这是写操作,我看到它在dmesg中恰好发生一次
  2. cat /dev/chardevexample。这是读数,dmesg显示它发生了两次。
  3. 我做了strace cat /dev/chardevexample,确实看到函数调用被两次调用以进行读取。之间也有一个写操作

    read(3, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 4096 write(1, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096hello4) = 4096 read(3, "", 131072)

  4. [dmesg读取后(猫命令)

    [909836.517402] DEBUG-device_read: To User hello4 and bytes_to_do 4096 ppos 0 # Read #1 [909836.517428] DEBUG-device_read: Data send to app hello4, nbytes=4096 # Read #1 [909836.519086] DEBUG-device_read: To User and bytes_to_do 0 ppos 4096 # Read #2 [909836.519093] DEBUG-device_read: Data send to app hello4, nbytes=0 # Read #2

  5. 随附用于读取,写入和file_operations的代码段。任何指导会有所帮助。我进行了广泛搜索,无法理解。因此,该职位。

    /*! * @brief Write to device from userspace to kernel space * @returns Number of bytes written */ static ssize_t device_write(struct file *file, //!< File pointer const char *buf,//!< from for copy_from_user. Takes 'buf' from user space and writes to //!< kernel space in 'buffer'. Happens on fwrite or write size_t lbuf, //!< length of buffer loff_t *ppos) //!< position to write to { int nbytes = lbuf - copy_from_user( buffer + *ppos, /* to */ buf, /* from */ lbuf); /* how many bytes */ *ppos += nbytes; buffer[strcspn(buffer, "\n")] = 0; // Remove End of line character pr_info("Recieved data \"%s\" from apps, nbytes=%d\n", buffer, nbytes); return nbytes; } /*! * @brief Read from device - from kernel space to user space * @returns Number of bytes read */ static ssize_t device_read(struct file *file,//!< File pointer char *buf, //!< for copy_to_user. buf is 'to' from buffer size_t lbuf, //!< Length of buffer loff_t *ppos)//!< Position { int nbytes; int maxbytes; int bytes_to_do; maxbytes = PAGE_SIZE - *ppos; if(maxbytes >lbuf) bytes_to_do = lbuf; else bytes_to_do = maxbytes; buffer[strcspn(buffer, "\n")] = 0; // Remove End of line character printk("DEBUG-device_read: To User %s and bytes_to_do %d ppos %lld\n", buffer + *ppos, bytes_to_do, *ppos); nbytes = bytes_to_do - copy_to_user( buf, /* to */ buffer + *ppos, /* from */ bytes_to_do); /* how many bytes*/ *ppos += nbytes; pr_info("DEBUG-device_read: Data send to app %s, nbytes=%d\n", buffer, nbytes); return nbytes;} /* Every Device is like a file - this is device file operation */ static struct file_operations device_fops = { .owner = THIS_MODULE, .write = device_write, .open = device_open, .read = device_read,};

linux kernel kernel-module chardev
1个回答
0
投票
用于指示文件结束的Unix约定是使read返回0字节。

在这种情况下,cat要求131072字节,仅接收4096。这是正常现象,不应解释为已到达文件末尾。例如,当您从键盘上读取但用户仅输入少量数据时,就会发生这种情况。

由于cat尚未看到EOF(即read并未返回0),因此它将继续发出read调用,直到发出EOF。这意味着如果有任何数据,您将始终至少看到两次读取调用:一次(或多次)读取数据,最后一次返回0。

© www.soinside.com 2019 - 2024. All rights reserved.