0

我了解fread()具有以下功能定义:

size_t fread(void *buffer, size_t size, size_t qty, FILE *inptr);

我也知道这inptr是一个文件指针,当使用该fopen()函数打开 FILE 指针时返回。我的问题是是否inptr将文件的每个字符/字母的内存地址存储在其内存中?如果是这种情况,是否将内存地址从inptrget 复制到*buffer(指向缓冲区数组的指针)?

还有一件事让我感到困惑。每次fread()调用时,size * qty都会复制/传输内存字节。是自己指向的文件inptr内容还是被复制/传输的文件内容的内存地址?

如果有人可以帮助我消除困惑,将不胜感激。谢谢 :)

4

4 回答 4

0

你可以认为是fread这样实现的:

size_t fread(char *ptr, size_t size, size_t nitems, FILE *fp)
{
    size_t i;
    for(i = 0; i < size * nitems; i++) {
        int c = getc(fp);
        if(c == EOF) break;
        *ptr++ = c;
}

(我省略了返回值,因为在我的简化插图中没有很好的方式来展示它。)

换句话说,fread读取一堆字符就像通过重复调用getc(). 所以显然这引出了如何getc工作的问题。

您必须知道的是FILE *指向一个结构,该结构以一种或另一种方式包含读入内存的一些(不一定是全部)文件字符的缓冲区。所以,在伪代码中,getc()看起来像这样:

int getc(FILE *fp)
{
    if(fp->buffer is empty) {
        fill fp->buffer by reading more characters from underlying file;
        if(that resulted in end-of-file)
            return EOF;
    }

    return(next character from fp->buffer);
}
于 2018-05-13T03:58:45.523 回答
0

问题的答案,

“fread() 是如何工作的?”

基本上是

“它要求您的操作系统为您读取文件。”

操作系统内核的唯一目的或多或少是代表您执行此类操作。内核托管磁盘和文件系统的设备驱动程序,并且无论文件存储在什么位置(例如,FAT32 格式的硬盘、网络共享等),都能够为您的程序获取数据。

fread() 要求操作系统从文件中获取数据的方式在操作系统和 CPU 之间略有不同。回到 MS-DOS 的过去,fread() 函数会将各种参数(根据您的程序提供给 fread() 的参数计算)加载到 CPU 寄存器中,然后引发中断。中断处理程序实际上是 MS-DOS 的一部分,然后会去获取请求的数据,并将其放置在内存中的给定位置。要加载的寄存器和要引发的中断都由 MS-DOS 手册指定。传递给 fread() 的参数是系统调用所需参数的抽象。

这就是所谓的系统调用。每个操作系统都有一个系统调用接口。Linux 上的 glibc 之类的库提供了方便的函数,例如 fread()(它是标准 C 库的一部分),并为您进行系统调用(操作系统之间没有标准化)。

请注意,这意味着 glibc 不是操作系统的基本部分。它只是一个例程库,围绕 Linux 提供的系统调用实现了 C 标准库。这意味着您可以使用替代的 C 库。例如,Android 不使用 glibc,即使它有一个 Linux 内核。

在 Windows 上也是如此。Windows 中的所有软件(C、C++、.NET 运行时等)都是为使用 WIN32 API 库 (win32.dll) 而编写的。在 Windows 上的不同是没有发布 NT 内核系统调用接口;我们不知道它是什么。

这导致了一些有趣的事情。

  • Linux 上的 WINE 重新创建 WIN32.dll,而不是 NT 内核系统调用接口。
  • Windows 10 上的适用于 Linux 的 Windows 子系统确实重新创建了 Linux 系统调用接口(这是可能的,因为它是公共知识)。
  • Solaris、QNX 和 FreeBSD 采用相同的技巧。
  • 更奇怪的是,MS 似乎为 Linux 做了一个 NT 内核系统接口 shim(即 WINE 没有做过的事情),以允许 MS-SQLServer 在 Linux 上运行。这实际上是 Windows 的 Linux 子系统。他们没有放弃这个。
于 2018-05-13T06:45:47.840 回答
0

你的问题有点令人困惑(这可能是你问他们的原因)所以我会尽力回答。

FILE *inptr是打开文件的句柄。你不直接读它,它只是用来告诉相关函数要操作什么。你可以把它想象成人类读取文件夹中的文件名,其中文件名用于标识文件,但内容以另一种方式访问​​。

至于数据,它是从用 fopen() 打开的文件中读取的,随后提供了一个文件句柄。数据不直接与 FILE 指针相关,通常您不应该直接弄乱 FILE 指针(不要尝试直接读取/写入)。

我尽量不要对操作过于技术化,因为您似乎是 C 的新手,但只是将其FILE *视为计算机在内部“命名”文件以供自己使用的方式,而数据缓冲区仅仅是内容。

于 2018-05-13T02:17:11.177 回答
0

FILE由您的操作系统实现。操作的功能FILE由您的系统实现。你不知道。要知道,您需要浏览操作系统的源代码。
inptr可能是指向您的操作系统分配的内存的指针。或者它可能是一个数字,您的操作系统使用它来查找它的数据。无论如何,它是一个句柄,您的系统使用它来查找FILE特定数据。并且您的系统决定该数据中的内容。出于缓存目的,可能所有字母都缓存在某个缓冲区中。也许不吧。
fread调用。从句柄Fread后面的底层实体读取数据。由您的系统解释,以访问底层内存或结构或设备或硬盘驱动器或打印机或键盘或鼠标或任何东西。它读到inptrinptrqty*size字节的数据。这些数据放在buffer. 那里没有放置指针。从设备读取的字节被放置在 指向的内存中buffer

于 2018-05-13T02:14:22.770 回答