为什么fseek使用read()系统调用? [英] Why does fseek use read() system call?

查看:165
本文介绍了为什么fseek使用read()系统调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解fseek的glibc实现.为此,我下载了glibc源代码并尝试了解其功能执行顺序.

I'm trying to understand the glibc implementation of fseek. To do so, I downloaded the glibc source code and tried to understand its function execution order.

我在libio/fseek.c中找到了fseek实现.基本上,它使用相同的参数调用函数(或宏)_IO_fseek().此宏在libio/iolibio.h中实现.

I found the fseek implementation in libio/fseek.c. Basically, it calls the function (or rather the macro) _IO_fseek() using the same parameters. This macro is implemented in libio/iolibio.h.

它定义为_IO_seekoff_unlocked (__fp, __offset, __whence, _IOS_INPUT|_IOS_OUTPUT)(在libio/ioseekoff.c中实现).执行此操作的下一步对我来说很令人困惑:

It is defined as _IO_seekoff_unlocked (__fp, __offset, __whence, _IOS_INPUT|_IOS_OUTPUT) (implemented in libio/ioseekoff.c). The next step in its execution is rather confusing for me:

_IO_seekoff_unlocked基本上返回_IO_SEEKOFF (fp, offset, dir, mode);,它返回_IO_seekoff_unlocked (fp, offset, dir, mode);,这应该创建一个调用循环.

_IO_seekoff_unlocked basically returns _IO_SEEKOFF (fp, offset, dir, mode);, which returns _IO_seekoff_unlocked (fp, offset, dir, mode);, which should create a call loop.

此外,在示例程序(seek.c)上使用strace时:

Also, when using strace on an example program (seek.c):

#include <stdio.h>

int main(void) {
    printf("[Fseek] Executing fseek\n");
    FILE *f = fopen("./seek.c", "rb");

    fseek(f, 0L, SEEK_END);
}

它表明fseek将调用read系统调用,即使我在glibc实现中找不到它.

it shows that fseek will call the read system call, even though I could not find it in the glibc implementation.

...
write(1, "[Fseek] Executing fseek\n", 24[Fseek] Executing fseek
) = 24
openat(AT_FDCWD, "./seek.c", O_RDONLY)  = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
lseek(3, 0, SEEK_SET)                   = 0
read(3, "#include <stdio.h>\n\nint main(voi"..., 146) = 146
exit_group(0)                           = ?
+++ exited with 0 +++

我的目标是了解此处如何使用读取系统调用.我有自己的read系统调用实现,对于我编写的其他测试来说效果很好,但是通过fseek调用时由于某些原因会失败.

My goal is to understand how the read system call is used here. I have my own implementation of the read system call, which works well for other tests I wrote but will fail for some reason when it is called via fseek.

作为示例,我在函数中使用fseek来获取文件的大小:

As an example, I use fseek in a function to get the size of a file:

long get_file_size(const char *name)
{
    FILE *temp_file = fopen(name, "rb");
    if (temp_file == NULL)
    {
        return -1;
    }

    fseek(temp_file, 0L, SEEK_END);
    long sz =  ftell(temp_file);
    fclose(temp_file);
    return sz;
}

此函数将使用正常" read实现返回正确的大小,但由于我的原因将失败.因此,如果有人能告诉我如何理解fseekread的用法(我在源代码中找不到),我将不胜感激.

This function will return the correct size with the "normal" read implementation but will fail with mine. So, if anybody can tell me how I can understand the use of read within fseek (which I could not find in the source), I would highly appreciate it.

推荐答案

JUMP3 (__seekoff, FP, OFF, DIR, MODE) . JUMP3 是调用FILE 跳转"表/vtable .

打开默认情况下分配 _IO_file_jumps (或者类似的东西,因为文件可以被映射等)作为新FILE的跳转表.它是FILE的跳转表/虚拟表的实现.

fopen by default assigns _IO_file_jumps (or something like that, because the file can be mmap-ed etc. etc.) as the jump table for new FILEs. It is the implementation of the jump table/virtual table for a FILE.

因此_IO_SEEKOFF调用 _IO_file_jumps->__seekoff .它指向 _IO_new_file_seekoff ,最后在其中函数会调用 _IO_SYSREAD . _IO_SYSREAD 从跳转表,依次调用 _IO_file_read ,它调用 __read 最终执行 .

So _IO_SEEKOFF calls _IO_file_jumps->__seekoff. It points to _IO_new_file_seekoff and finally inside that function a call is made to _IO_SYSREAD. _IO_SYSREAD calls _read from the jump table, which in turn calls _IO_file_read, which calls __read which finally executes SYSCALL_CANCEL (read).

这篇关于为什么fseek使用read()系统调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆