_IO_FILE 구조체

dandb3·2023년 5월 30일
0

pwnable

목록 보기
4/19
  • _IO_FILE 구조체
struct _IO_FILE
{
  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */

  /* The following pointers correspond to the C++ streambuf protocol. */
  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;
  int _flags2;
  __off_t _old_offset; /* This used to be _offset but it's too small.  */

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

  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

struct _IO_FILE_complete
{
  struct _IO_FILE _file;
#endif
  __off64_t _offset;
  /* Wide character stream stuff.  */
  struct _IO_codecvt *_codecvt;
  struct _IO_wide_data *_wide_data;
  struct _IO_FILE *_freeres_list;
  void *_freeres_buf;
  size_t __pad5;
  int _mode;
  /* Make sure we don't get into trouble again.  */
  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
typedef struct _IO_FILE FILE;

결국 FILEstruct _IO_FILE의 typedef였다.

  • _flags 멤버변수

    • open된 상태를 저장하는 플래그이다.

    • 앞 2바이트는 매직넘버 0xfbad로 고정되고, 뒤의 2바이트가 플래그의 의미로써 사용된다.

    • 플래그의 값들은 다음과 같다.

      /* Magic number and bits for the _flags field.  The magic number is
         mostly vestigial, but preserved for compatibility.  It occupies the
         high 16 bits of _flags; the low 16 bits are actual flag bits.  */
      
      #define _IO_MAGIC         0xFBAD0000 /* Magic number */
      #define _IO_MAGIC_MASK    0xFFFF0000
      #define _IO_USER_BUF          0x0001 /* Don't deallocate buffer on close. */
      #define _IO_UNBUFFERED        0x0002
      #define _IO_NO_READS          0x0004 /* Reading not allowed.  */
      #define _IO_NO_WRITES         0x0008 /* Writing not allowed.  */
      #define _IO_EOF_SEEN          0x0010
      #define _IO_ERR_SEEN          0x0020
      #define _IO_DELETE_DONT_CLOSE 0x0040 /* Don't call close(_fileno) on close.  */
      #define _IO_LINKED            0x0080 /* In the list of all open files.  */
      #define _IO_IN_BACKUP         0x0100
      #define _IO_LINE_BUF          0x0200
      #define _IO_TIED_PUT_GET      0x0400 /* Put and get pointer move in unison.  */
      #define _IO_CURRENTLY_PUTTING 0x0800
      #define _IO_IS_APPENDING      0x1000
      #define _IO_IS_FILEBUF        0x2000
                                 /* 0x4000  No longer used, reserved for compat.  */
      #define _IO_USER_LOCK         0x8000
  • struct _IO_FILE *_chain 멤버변수

    • 리스트 형태로 다른 FILE 구조체들과 single linked list 형태로 연결된다.
    • 전역 변수 _IO_list_all을 통해서 관리된다.
    • 프로그램 시작 시 stdin, stdout, stderr의 순서로 FILE 구조체가 만들어지고, LIFO의 형식으로 연결된다.
  • 입출력의 효율?

    • 입출력이 이루어질 때에는 필요할 때마다 입출력을 수행하게 된다면 효율이 매우 떨어지게 된다. 그래서 버퍼를 이용하여 버퍼 크기만큼 미리 입출력을 해놓고, 그 이후에 필요할 때마다 그 버퍼에서 값을 가져오는 방식으로 동작을 하게 된다. 아래는 그 예시이다.
      • 커널과 Disk 사이의 구조

        그림을 보면 알 수 있듯이, 커널은 내부적으로 버퍼를 사용하여 HD I/O횟수를 줄일 수 있다.
      • 유저공간과 커널공간 사이의 구조

        이 경우에는 context switch의 비용 절감을 위해서 usermode에서 버퍼를 사용한다.
  • _IO_... 멤버변수들

    • 이제 위 멤버변수들의 의미에 대해서 알 수 있을 것이다.
    • _IO_buf_base, _IO_buf_end
      • 내부적으로 할당된 버퍼의 시작점과 끝점(물론 버퍼의 마지막 element + 1위치)을 가리키는 포인터들이다.
    • _IO_read_ptr, _IO_read_base, _IO_read_end
      • fread함수 호출시에 사용되는 포인터들이다.
      • 각각 버퍼에서 현재까지 read한 위치, read한 시작점, read한 끝점을 가리킨다.
      • fread함수를 설명하면서 자세하게 설명할 예정이다.
    • _IO_write_ptr, _IO_write_base, _IO_write_end
      • fwrite함수 호출시에 사용되는 포인터들이다.
      • 각각 버퍼에서 현재까지 write한 위치, write한 시작점, write한 끝점을 가리킨다.
      • fwrite함수를 설명하면서 자세하게 설명할 예정이다.
  • _fileno 멤버변수

    • fopen 시에 내부적으로 open시스템 콜을 호출하여 리턴된 fd값이 저장된다.
    • fwrite 혹은 fread 함수는 내부적으로 write, read 시스템 콜을 호출하게 되는데, 이 때 fd값으로 사용된다.
  • 설명 안 한 것들이 많지만, 일단은 이 정도로만...

  • 참고 자료

profile
공부 내용 저장소

0개의 댓글