Как на самом деле работает фред в С? - PullRequest
0 голосов
/ 13 мая 2018

Я понимаю, что fread() имеет следующее определение функции:

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

Я также понимаю, что inptr - это указатель файла, который возвращается, когда указатель FILE открывается с использованием функции fopen(),Мой вопрос: inptr хранит адрес памяти каждого отдельного символа / буквы файла в его памяти?Если это так, адреса памяти из inptr копируются в *buffer (указатель на массив буферов)?

Есть еще одна вещь, которая меня смущает.Каждый раз, когда вызывается fread(), копируется / передается size * qty байт памяти.Является ли содержимое файла указанным самим inptr или адрес памяти содержимого файла, который копируется / передается?

Буду признателен, если кто-нибудь поможет мне устранить путаницу.Спасибо:)

Ответы [ 4 ]

0 голосов
/ 13 мая 2018

Ответ на вопрос

"как работает fread ()?"

в основном

"он просит вашу операционную систему прочитать файл для вас."

Более или менее единственной целью ядра операционной системы является выполнение таких действий, какэто от вашего имени.В ядре размещены драйверы устройств для дисков и файловых систем, и он может извлекать данные для вашей программы независимо от того, где хранится файл (например, жесткий диск в формате FAT32, сетевой ресурс и т. Д.).

Способ, которым fread () запрашивает у вашей операционной системы выборку данных из файла, немного отличается в зависимости от ОС и процессора.В старые добрые времена MS-DOS функция fread () загружала различные параметры (рассчитанные из параметров, которые ваша программа передала fread ()) в регистры ЦП, а затем вызывала прерывание.Обработчик прерываний, который на самом деле был частью MS-DOS, затем отправлял запрашиваемые данные и помещал их в определенное место в памяти.Регистры, которые должны быть загружены, и вызываемое прерывание были определены в руководствах MS-DOS.Параметры, передаваемые в fread (), являются абстракциями тех, которые нужны системному вызову.

Это то, что называется системным вызовом.Каждая операционная система имеет интерфейс вызова системы.Такие библиотеки, как glibc в Linux, предоставляют удобные функции, такие как fread () (которая является частью стандартной библиотеки C) и выполняют системный вызов для вас (который не стандартизирован между операционными системами).

Обратите внимание, что это означаетчто glibc не является фундаментальной частью операционной системы.Это просто библиотека подпрограмм, которая реализует стандартную библиотеку C вокруг системных вызовов, которые предоставляет Linux.Это означает, что вы можете использовать альтернативную библиотеку C.Например, Android не использует glibc, даже если у него ядро ​​Linux.

Аналогично в Windows.Все программное обеспечение в Windows (C, C ++, среда выполнения .NET и т. Д.) Написано для использования библиотеки API WIN32 (win32.dll).Разница в Windows заключается в том, что интерфейс системного вызова ядра NT не публикуется;мы не знаем что это.

Это приводит к некоторым интересным вещам.

  • WINE в Linux воссоздает WIN32.dll, а не интерфейс системного вызова ядра NT.
  • Подсистема Windows для Linux в Windows 10 воссоздает интерфейс системных вызовов Linux (что возможно, потому что это общеизвестно).
  • Solaris, QNX и FreeBSD используют один и тот же прием.
  • Еще более странно, что похоже, что MS разработала оболочку интерфейса системы NT для Linux (то есть то, чего не сделал WINE), чтобы MS-SQLServer мог работать в Linux.По сути, это подсистема Linux для Windows.Они не отдали это.
0 голосов
/ 13 мая 2018

Ваши вопросы немного сбивают с толку (возможно, поэтому вы их задаете), поэтому я сделаю все возможное, чтобы ответить.

FILE *inptr - дескриптор открытого файла.Вы не читаете его напрямую, он просто используется, чтобы сообщить связанным функциям, над чем работать.Вы можете думать об этом как о человеке, читающем имя файла в папке, где имя файла используется для идентификации файла, но доступ к содержимому осуществляется другим способом.

Что касается данных, то эточитать из файла, который открывается с помощью fopen () и впоследствии предоставляет дескриптор файла.Данные напрямую не связаны с указателем FILE, и, как правило, вы не должны связываться с указателем FILE напрямую (не пытайтесь читать / записывать из него напрямую).

Я пытался не быть слишком техническимЧто касается операции, то, похоже, вы новичок в C, но просто подумайте о FILE * как о способе компьютера «именовать» файл внутри себя для собственного использования, а буфер данных - это просто содержимое.

0 голосов
/ 13 мая 2018

Вы можете представить, что 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);
}
0 голосов
/ 13 мая 2018

FILE реализован в вашей операционной системе.Функции, работающие на FILE, реализуются вашей системой.Вы не знаетеЧтобы знать, вам нужно просмотреть источники вашей операционной системы.
inptr может быть указателем на память, выделенную вашей операционной системой.Или это может быть число, которое ваша операционная система использует для поиска своих данных.В любом случае, это дескриптор, который ваша система использует для поиска FILE конкретных данных.И ваша система решает, что находится в этих данных.В целях кэширования, возможно, все буквы кэшируются в некотором буфере.Возможно, нет.
фред звонок.Fread читает данные из базового объекта за inptr дескриптором.inptr интерпретируется вашей системой для доступа к основной памяти, структуре, устройству, жесткому диску, принтеру, клавиатуре, мыши или чему-либо еще.Он читает qty*size байтов данных.Эти данные помещаются в buffer.Там нет указателей.Байты, считанные с устройства, помещаются в память, на которую указывает buffer.

...