为什么 cat 调用 read() 两次就足够了?
Why does cat call read() twice when once was enough?
我是 Linux 内核模块的新手。我正在学习基于网络课程的字符驱动程序模块。我有一个创建 /dev/chardevexample
的非常简单的模块,我有一个问题需要理解:
当我执行 echo "hello4" > /dev/chardevexample
时,我看到 write
按预期执行了一次。但是,当我执行 cat /dev/chardevexample
时,我看到读取执行了 两次 次。
我在我的代码和课程中都看到了这一点 material。第一次read()
就返回了所有数据,为什么cat
又调用一次呢?
到目前为止我所做的所有事情如下:
insmod chardev.ko
加载我的模块
echo "hello4" > /dev/chardevexample
。这是写入,我在 dmesg 中看到它只发生了一次
cat /dev/chardevexample
。这是读取,dmesg
显示它发生了两次。
我做了 strace cat /dev/chardevexample
,我确实看到函数调用被调用两次以进行读取。中间也有写
read(3, "hello4[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]"..., 131072) = 4096
write(1, "hello4[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]"..., 4096hello4) = 4096
read(3, "", 131072)
dmesg
读取后(cat 命令)
[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
附上读取、写入和 file_operations 的代码片段。任何
指导会有所帮助。我广泛搜索,无法理解。
因此 post.
/*!
* @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,};
指示文件结束的 Unix 约定是 read
return 0 字节。
在这种情况下,cat
要求 131072 字节,但只收到 4096。这是正常的,不应被解释为已到达文件末尾。例如,当您从键盘读取但用户仅输入少量数据时,就会发生这种情况。
因为 cat
还没有看到 EOF(即 read
没有 return 0),它会继续发出 read
调用直到它看到。这意味着如果有任何数据,您将始终看到至少两个读取调用:一个(或多个)用于数据,最后一个 returns 0.
我是 Linux 内核模块的新手。我正在学习基于网络课程的字符驱动程序模块。我有一个创建 /dev/chardevexample
的非常简单的模块,我有一个问题需要理解:
当我执行 echo "hello4" > /dev/chardevexample
时,我看到 write
按预期执行了一次。但是,当我执行 cat /dev/chardevexample
时,我看到读取执行了 两次 次。
我在我的代码和课程中都看到了这一点 material。第一次read()
就返回了所有数据,为什么cat
又调用一次呢?
到目前为止我所做的所有事情如下:
insmod chardev.ko
加载我的模块echo "hello4" > /dev/chardevexample
。这是写入,我在 dmesg 中看到它只发生了一次
cat /dev/chardevexample
。这是读取,dmesg
显示它发生了两次。我做了
strace cat /dev/chardevexample
,我确实看到函数调用被调用两次以进行读取。中间也有写read(3, "hello4[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]"..., 131072) = 4096 write(1, "hello4[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]"..., 4096hello4) = 4096 read(3, "", 131072)
dmesg
读取后(cat 命令)[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
附上读取、写入和 file_operations 的代码片段。任何 指导会有所帮助。我广泛搜索,无法理解。 因此 post.
/*! * @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,};
指示文件结束的 Unix 约定是 read
return 0 字节。
在这种情况下,cat
要求 131072 字节,但只收到 4096。这是正常的,不应被解释为已到达文件末尾。例如,当您从键盘读取但用户仅输入少量数据时,就会发生这种情况。
因为 cat
还没有看到 EOF(即 read
没有 return 0),它会继续发出 read
调用直到它看到。这意味着如果有任何数据,您将始终看到至少两个读取调用:一个(或多个)用于数据,最后一个 returns 0.