2013-05-15 2 views
1

Я смущен тем, что ОС фактически «открывает» файл на C, когда вы делаете fopen в коде. Для разработки, предположим, у меня было 100 двоичных файлов (скажем, размером 1 MB), который я открываю в CУказатели памяти и файлов

FILE **fptr; 

fptr = calloc(100, sizeof(FILE *)); 

for (ii = 0; ii < 100; ii++) 
    fptr[ii] = fopen(filename[ii], "rb+"); 

Предположим, что filename и ii были уже определены соответствующим образом.

Будет ли ОС загружать 100 MB в память, или приведенный выше код просто сообщает программе, что эти файлы готовы к доступу?

+1

'fopen'doesn't не читает весь файл, как вы говорите: сохраняйте эти файлы только для получения доступа –

+1

Это зависит от того, что вы подразумеваете под« готовностью к доступу ». ОС может свободно откручивать жесткий диск, поэтому для считывания данных может потребоваться несколько секунд, так как диск вращается.Единственная гарантия заключается в том, что файл существует, и у вас есть разрешение на его открытие. –

ответ

3

Последнее, данные не считываются из файла до тех пор, пока не понадобится, то есть когда вы вызываете fread() или какую-либо другую функцию ввода-вывода.

Конечно, базовая операционная система может решить, чтобы читать данные при открытии файла, чтобы сэкономить время позже, но это вне вашего контроля, поэтому в действительности это не имеет значения. Я имею в виду, что это не имеет значения, потому что любая память, используемая такой спекулятивной буферизацией, должна быть немедленно доступна для приложений по требованию.

Это не похоже на то, что любая практическая система позволит fopen() потратить время на чтение 100 МБ, хотя это будет очень плохой инженер.

Также обратите внимание, что могут быть ограничения на количество файлов, которые может открывать один процесс параллельно. 100, однако, должно быть хорошо для большинства современных систем.

+0

@GrahamBorland Да, полностью, уже исправлено, но спасибо. – unwind

-2

Реализация определена. Вы не обязаны читать весь файл в памяти на fopen(). Большинство реализаций в наши дни используют некоторую форму mmap() для фактического чтения данных в память.

+1

Можете ли вы назвать реализацию, которая использует 'mmap()' во время 'fopen()'? У меня есть сомнения. –

+0

Не the downvoter, но я действительно сомневаюсь в этом, цитируя стандартный 'fopen', открывается файл, имя которого является строкой, на которую указывает имя файла, и связывает с ней поток. –

+0

Я не говорил во время fopen(). Я сказал, что в большинстве случаев использование mmap() возможно, особенно при использовании больших файлов. Это вся реализация определена, реализация может делать все, что ей нравится. В последних версиях glibc был добавлен флаг fopen(), указывающий, что пользователь предпочитает mmap(). –

1

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

0

Есть несколько вещей, которые мы должны смотреть на первый

  1. ФАЙЛ

это typedefed ниже

stdio.h: 

typedef struct _IO_FILE FILE; 

следующий _IO_FILE

_IO_FILE выглядит, как показано ниже:

libio.h: 

struct _IO_FILE { 
    int _flags;  /* High-order word is _IO_MAGIC; rest is flags. */ 
#define _IO_file_flags _flags 

    /* The following pointers correspond to the C++ streambuf protocol. */ 
    /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ 
    char* _IO_read_ptr; /* Current read pointer */ 
    char* _IO_read_end; /* End of get area. */ 
    char* _IO_read_base; /* Start of putback+get area. */ 
    char* _IO_write_base; /* Start of put area. */ 
    char* _IO_write_ptr; /* Current put pointer. */ 
    char* _IO_write_end; /* End of put area. */ 
    char* _IO_buf_base; /* Start of reserve area. */ 
    char* _IO_buf_end; /* End of reserve area. */ 
    /* The following fields are used to support backing up and undo. */ 
    char *_IO_save_base; /* Pointer to start of non-current get area. */ 
    char *_IO_backup_base; /* Pointer to first valid character of backup area */ 
    char *_IO_save_end; /* Pointer to end of non-current get area. */ 

    struct _IO_marker *_markers; 

    struct _IO_FILE *_chain; 

    int _fileno; 
#if 0 
    int _blksize; 
#else 
    int _flags2; 
#endif 
    _IO_off_t _old_offset; /* This used to be _offset but it's too small. */ 

#define __HAVE_COLUMN /* temporary */ 
    /* 1+column number of pbase(); 0 is unknown. */ 
    unsigned short _cur_column; 
    signed char _vtable_offset; 
    char _shortbuf[1]; 


    /* char* _save_gptr; char* _save_egptr; */ 

    _IO_lock_t *_lock; 
#ifdef _IO_USE_OLD_IO_FILE 
}; 

и цепочка внутренних указателей продолжаются, однако эта файловая структура никоим образом не сохраняет данные с собой, что это поддерживает, является снимком записи и представляет пользователю пространство. если пользователь запрашивает чтение данных из файла, будет использоваться тот же FILE *, но данные будут получены с помощью syscall (в случае чтения в режиме Linux), состояние смещения, однако, будет сохраняться здесь, чтобы идти вперед, назад. самое главное это обеспечивает очень хорошую абстракцию для внутренних системных вызовов.

Смежные вопросы