1

コードでを実行するときに、OS が実際に C でファイルを「開く」方法について混乱してfopenいます。1 MB詳しく説明すると、C で開く100 個のバイナリ ファイル (たとえば、サイズ) があるとします。

FILE **fptr;

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

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

filenameiiが既に適切に定義されていると仮定します。

OS100 MBはメモリに読み込まれますか、それとも上記のコードは、これらのファイルをアクセス可能な状態に保つようにプログラムに指示するだけですか?

4

4 に答える 4

3

後者の場合、必要になるまで、つまり、fread()または他の I/O 関数を呼び出すまで、ファイルからデータは読み取られません。

もちろん、基盤となるオペレーティング システムは、後で時間を節約するために、ファイルが開かれたときに投機的にデータを読み取ることを決定する可能性がありますが、それは制御できないため、実質的には問題ではありません。このような投機的バッファリングで使用されるメモリは、アプリケーションがオンデマンドですぐに利用できるようにする必要があるため、問題ではありません。

とは言っても、実用的なシステムfopen()で 100 MB を読み取るのに必要な時間を費やせるわけではありませんが、それは非常に悪いエンジニアリングです。

また、1 つのプロセスが並行して開くことができるファイルの数には制限がある場合があることにも注意してください。ただし、最近のほとんどのシステムでは 100 で十分です。

于 2013-05-15T10:21:41.303 に答える
1

ファイルを開くときに、ファイルはメモリにロードされません。代わりに、読み取りごとにパーツがロードされます。fopen の呼び出しによって、メディアからファイル コンテンツが読み取られることはありません。fread によって、メディアから部分的な読み取り (または小さなファイルの場合は完全な読み取り) が行われます。部分読み取りは通常、キャッシュ マネージャーのキャッシュ ライン サイズと同じです。

于 2013-05-15T10:32:10.690 に答える
0

最初に確認しなければならないことがいくつかあります

  1. ファイル

これは以下のように型定義されています

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 の場合は read 呼び出し) によって取得されますが、オフセット状態はここで保持され、前方、後方に移動します。最も重要なことは、これが内部システム コールに非常に優れた抽象化を提供することです。

于 2013-05-15T10:55:36.603 に答える