首页 文章

调用read()返回0但缓冲区已更改,调用fread()读取相同的偏移量时没有发生

提问于
浏览
1

如果我通过调用read()读取文件,如下所示:

unsigned char buf[512];
memset(buf, 0, sizeof(unsigned char) * 512);
int fd;
int readcount;
int offset = 10315001; /* file size is 14315504 */

fd = open("myfile", O_RDONLY);
lseek(fd, offset, SEEK_SET);
readcount = read(fd, (void*)buf, 8);
close(fd);

read()返回0,但“buf”的内存已更改(不再为0) . 如果我尝试使用fread()读取相同的偏移量和相同的文件,如下所示:

FILE* file;
file = fopen("myfile", "r");
fseek(file, offset, SEEK_SET);
readcount = fread((void*)buf, 8, 1, file);
fclose(file);

fread()返回0,但buf和以前一样 .

如果read()失败,为什么它会改变“buf”的内存空间?还是我犯了一些错误?

感谢帮助 : )

Edit: Every time I ran the code above, the "buf" changed by read() in the same way -> from 0 to the same values. So the changed "buf" may not be random values?

Edit 2: The offset parameter is valid(thanks twalberg), and if I read another valid offset, both read() and fread() will be succeeded and the result of "buf" is the same. Is there any way to find what's wrong when read() failed? The errno is "No errors" when read() returns 0.

2 回答

  • 1

    调用 read() 失败或成功的零字节 read() 后缓冲区的内容未定义 .

    可能发生的事情是它为临时存储分配了一个内部(可能是内核端)缓冲区(它填充了不同的垃圾)并将缓冲区复制到缓冲区中,但实际上没有写入缓冲区 .

    由于您只需要在成功读取后检查缓冲区,这应该无关紧要 . 如果您在该缓冲区中有重要数据,请将其移出该处,然后再将其传递给可能会删除该数据的函数!

    Edit: 代码看起来像这样 . 想象一下 kernel_read() 是从文件描述符中读取的系统调用,它需要一个在内核's address space rather than the process'地址空间中分配的缓冲区(因为内核看起来很奇怪 . )

    extern __kernel void *kernel_malloc(size_t size);
    extern void kernel_copy_from_kernel_to_userland(void *dest, __kernel void *src, size_t size);
    extern void kernel_free(__kernel void *address);
    
    extern int kernel_is_valid_fd(int fd);
    extern ssize_t kernel_read(int fd, __kernel void *kbuf, size_t count);
    
    ssize_t read(int fd, void *buf, size_t count) {
        ssize_t result = -1;
    
        if (0 == kernel_is_valid_fd(fd)) {
            __kernel void *kernelbuf = kernel_malloc(count);
            if (kernelbuf) {
                result = kernel_read(fd, kernelbuf, count);
                kernel_copy_from_kernel_to_userland(buf, kernelbuf, count);
                kernel_free(kernelbuf);
            } else {
                errno = ENOMEM;
            }
        } else {
            errno = EINVAL;
        }
    
        return result;
    }
    

    这是一个思想实验,不是来自任何运输操作系统的真实实现,但也许它可以帮助您理解为什么您可能已经看到了您所看到的 .

  • 2

    我想我已经发现了这里发生了什么 . 该文件是二进制文件,但我用文本模式(O_RDONLY)读取()它 .

    偏移量10315001的值为0x1a,当read()和fread()函数在文本模式下满足0x1a时,它们都将返回0, but the different is, the read() will still write the buf with binary mode, while fread() won't do this.

相关问题