数据内容,当读取操作在 C 中失败时



关于 C lib 函数读取,是否定义了当读取操作失败时数据会发生什么(count = -1)?假设"数据"仍然保留以前的值;如果当前读取操作失败,它会被覆盖吗?在我当前的实现中,调试显示旧值仍然存在,但是是否有"正式"定义的内容? 请考虑以下代码:

int8_t count = 0;
int fd = open(I2C_BUS, O_RDWR);
if (fd < 0) {
fprintf(stderr, "Failed to open device: %sn", strerror(errno));
return(-1);
}
...
count = read(fd, data, length);
if (count < 0) {
fprintf(stderr, "Failed to read device(%d): %sn", devAddr, ::strerror(errno));
close(fd);
return(-1);

TL;DR - 它没有标准化,它取决于文件系统的实现。


要回答您的问题,我们应该首先看看当您致电read时会发生什么。

libc 提供的大多数"基本"函数实际上是内核系统调用的包装。让我们看一下libcread的代码,在read.c中找到:

/* Read NBYTES into BUF from FD.  Return the number read or -1.  */
ssize_t
__libc_read (int fd, void *buf, size_t nbytes)
{
return SYSCALL_CANCEL (read, fd, buf, nbytes);
}
libc_hidden_def (__libc_read)
weak_alias (__libc_read, read)

如您所见,libc 的read实际上调用了系统调用read

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
struct fd f = fdget(fd);
ssize_t ret = -EBADF;
if (f.file) {
loff_t pos = file_pos_read(f.file);
ret = vfs_read(f.file, buf, count, &pos);
file_pos_write(f.file, pos);
fdput(f);
}
return ret;
}

然后,系统调用read调用vfs_read,它是VFS的一部分(代表VirtualFileSystem)。VFS 是文件系统的抽象层。每个文件系统都注册了一堆 VFS 知道要调用的回调函数。

例如,让我们看一下尝试从ext4文件系统读取文件时调用的函数链:

read()           ---> libc
|
|
__libc_read()    ---> libc
|
|
syscall_read()   ---> kernel; found in linux/fs/read_write.c
|
|
vfs_read()       ---> kernel; found in linux/fs/read_write.c
|
|
new_sync_read()  ---> kernel; found in linux/fs/read_write.c
|
|
generic_file_read_iter() ---> ext4's read function; found in fs/ext/ext4
|
|
...

它一直持续到调用最后一个内部函数。您从调用 libc 的read函数时收到的返回值是从上述函数返回的。

但是,重要的是要说大多数filsystems(包括ext4!)最终调用了一些通用内核的函数,例如mm/filemap.c中的do_generic_file_read函数。 回到你的问题 -这取决于文件系统选择实现read()的方式,并且没有标准化


所以最重要的是 - 大多数文件系统在发生错误时会以类似的方式处理缓冲区,但您无法保证。实际上,您的数据可能会保持不变,因为没有理由更改。

作为建议,如果你想知道到底发生了什么,你可以随时参考内核的源代码:)

此致敬意。

最新更新