C中的fread实际上是如何工作的?
我了解C中的fread实际上是如何工作的?,c,pointers,fread,file-pointer,C,Pointers,Fread,File Pointer,我了解fread()具有以下函数定义: size_t fread(void *buffer, size_t size, size_t qty, FILE *inptr); 我还了解到,inptr是一个文件指针,在使用fopen()函数打开文件指针时返回。我的问题是inptr是否将文件中每个字符/字母的内存地址存储在其内存中?如果是这种情况,是否将inptr中的内存地址复制到*缓冲区(指向缓冲区数组的指针) 还有一件事我很困惑。每次调用fread()。是由inptr本身指向的文件内容,还是正在复
fread()
具有以下函数定义:
size_t fread(void *buffer, size_t size, size_t qty, FILE *inptr);
我还了解到,inptr
是一个文件指针,在使用fopen()
函数打开文件指针时返回。我的问题是inptr
是否将文件中每个字符/字母的内存地址存储在其内存中?如果是这种情况,是否将inptr
中的内存地址复制到*缓冲区
(指向缓冲区数组的指针)
还有一件事我很困惑。每次调用fread()。是由inptr
本身指向的文件内容,还是正在复制/传输的文件内容的内存地址
如果有人能帮我消除困惑,我将不胜感激。谢谢:)文件由您的操作系统实现。在文件
上操作的功能由您的系统实现。你不知道。要知道,您需要浏览操作系统的源代码。
inptr
可能是指向操作系统分配的内存的指针。或者它可能是一个数字,您的操作系统使用它来查找数据。无论如何,它是一个句柄,您的系统使用它来查找文件
特定数据。你的系统决定了数据中的内容。出于缓存目的,可能所有字母都缓存在某个缓冲区中。也许不会。
打电话Fread
从inptr
句柄后面的底层实体读取数据inptr
由您的系统进行解释,以访问底层内存、结构、设备、硬盘驱动器、打印机、键盘或鼠标等。它读取qty*size
字节的数据。这些数据放在缓冲区中。那里没有指针。从设备读取的字节被放在缓冲区指向的内存中。你的问题有点让人困惑(这可能就是你问这些问题的原因),所以我会尽力回答
FILE*inptr
是打开文件的句柄。您不直接阅读它,它只是用来告诉相关函数操作什么。你可以把它想象成一个人在文件夹中读取文件名,文件名用来标识文件,但内容是通过另一种方式访问的
至于数据,它是从用fopen()打开的文件中读取的,随后提供了一个文件句柄。数据与文件指针没有直接关联,通常不应该直接干扰文件指针(不要尝试直接读取/写入)
我试着对操作不要太过技术化,因为你似乎对C不太熟悉,但只是把文件*
看作是计算机内部“命名”文件以供自己使用的方式,而数据缓冲区仅仅是内容。你可以把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;
}
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);
}
问题的答案是,
“fread()是如何工作的?”
基本上
“它要求操作系统为您读取文件。”
或多或少,操作系统内核的唯一目的是代表您执行类似的操作。内核承载磁盘和文件系统的设备驱动程序,并且无论文件存储在什么位置(例如FAT32格式的HDD、网络共享等),都能够为您的程序获取数据
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上的Windows Linux子系统确实重新创建了Linux系统调用接口(这是可能的,因为它是公共知识)
- Solaris、QNX和FreeBSD采用了相同的技巧李>
- 更奇怪的是,看起来微软已经为Linux做了一个NT内核系统接口垫片(也就是说,WINE没有做过的事情),以允许微软SQLServer在Linux上运行。这实际上是一个适用于Windows的Linux子系统。他们没有把这个给别人李>
我的问题是inptr是否将文件中每个字符/字母的内存地址存储在其内存中?检查文件
包含的内容,读取此结构的成员。打开vi/usr/include/libio.h
&查找文件的定义