제2 장 부분 연습 문제 에 관 한 지식 정리

8683 단어 shell
open 과 fopen 의 차이 (2.3)
1. 버퍼 파일 시스템
버퍼 파일 시스템 의 특징 은 메모리 에 '버퍼' 를 열 어 프로그램의 모든 파일 에 사용 하 는 것 입 니 다. 파일 을 읽 는 작업 을 수행 할 때 디스크 파일 에서 데 이 터 를 메모리 '버퍼' 에 먼저 읽 고 가득 채운 다음 메모리 '버퍼' 에서 받 은 변 수 를 읽 습 니 다.파일 을 쓰 는 작업 을 수행 할 때 먼저 데 이 터 를 메모리 '버퍼' 에 기록 하고 메모리 '버퍼' 가 가득 찬 후에 파일 을 기록 합 니 다.이 를 통 해 알 수 있 듯 이 메모리 '버퍼' 의 크기 는 실제 작업 의 외부 저장 횟수 에 영향 을 주 고 메모리 '버퍼' 가 클 수록 외부 저장 횟수 가 적 고 실행 속도 가 빠 르 며 효율 이 높다.일반적으로 파일 '버퍼' 의 크기 는 랜 덤 으로 정 해 집 니 다.fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind 등 2. 비 버퍼 파일 시스템 버퍼 파일 시스템 은 파일 구조 체 지침 을 통 해 파일 을 관리 하고 파일 지침 을 통 해 파일 에 접근 합 니 다. 문자, 문자열, 포맷 데 이 터 를 읽 을 수도 있 고 바 이 너 리 데 이 터 를 읽 을 수도 있 습 니 다.비 버퍼 파일 시스템 은 운영 체제 에 의존 하여 운영 체제 의 기능 을 통 해 파일 을 읽 고 쓰 는 시스템 급 입 출력 입 니 다. 파일 구조 체 지침 을 설정 하지 않 고 바 이 너 리 파일 만 읽 을 수 있 지만 효율 이 높 고 속도 가 빠 릅 니 다. ANSI 기준 은 비 버퍼 파일 시스템 을 포함 하지 않 기 때문에 선택 하지 않 는 것 이 좋 습 니 다.이 책 은 간단 한 소개 만 한다.open, close, read, write, getc, getchar, putc, putchar 등.
open 은 fopen 에 비해 전 자 는 저급 IO 에 속 하고 후 자 는 고급 IO 이다.전 자 는 파일 설명자 (사용자 프로그램 구역 의) 를 되 돌려 주 고 후 자 는 파일 지침 을 되 돌려 줍 니 다.전 자 는 버퍼 가 없고 후 자 는 버퍼 가 있다.전 자 는 read, write 등 과 함께 사용 하고 후 자 는 free ad, fwrite 등 과 함께 사용한다.후 자 는 전 자 를 바탕 으로 확 대 된 것 으로 대부분의 경우 후 자 를 사용한다.
open 은 시스템 호출 에서 파일 핸들 을 되 돌려 줍 니 다. 파일 의 핸들 은 파일 설명 부 표 에 있 는 색인 입 니 다. fopen 은 C 의 라 이브 러 리 함수 이 고 파일 구 조 를 가리 키 는 지침 을 되 돌려 줍 니 다.
C 언어 FILE 구조 체 와 버퍼 에 대한 깊이 있 는 연구 (2.4) 는 C 언어 에서 하나의 포인터 변수 로 파일 을 가리 키 는데 이 지침 을 파일 포인터 라 고 한다.파일 포인터 로 가리 키 는 파일 을 여러 가지 조작 할 수 있 습 니 다.
파일 포인터 의 일반적인 형식 을 정의 합 니 다: FILE * fp;
이 곳 의 FILE 는 실제 stdio. h 에서 정 의 된 구조 체 로 이 구조 체 에는 파일 이름, 파일 상태, 파일 현재 위치 등 정보 가 포함 되 어 있 습 니 다.우 리 는 fopen 을 통 해 파일 포인터 (FILE 구조 체 를 가리 키 는 포인터) 를 되 돌려 파일 작업 을 합 니 다.
메모: FILE 는 파일 버퍼 의 구조 이 고 fp 도 파일 버퍼 를 가리 키 는 지침 입 니 다.
컴 파일 러 stdio. h 헤더 파일 에 따라 FILE 에 대한 정의 가 약간 차이 가 있 습 니 다. 여기 서 표준 C 로 예 를 들 어 설명 합 니 다.
 1. #define NULL 0
  2. #define EOF (-1)
  3. #define BUFSIZ 1024
  4. #define OPEN_MAX 20 //           
  5. //   FILE   
  6. typedef struct _iobuf {
  7. int cnt; //      ,        ,                    
  8. char *ptr; //              
  9. char *base; //       
  10. int flag; //        
  11. int fd; //      
  12. } FILE;
  13. extern FILE _iob[OPEN_MAX];
  14. #define stdin (&_iob[0]) // stdin        0
  15. #define stdout (&_iob[1]) // stdout        1
  16. #define stderr (&_iob[2]) // stdout        2
  17. enum _flags {
  18. _READ =01, //    
  19. _WRITE =02, //    
  20. _UNBUF =04, //    
  21. _EOF = 010, //     EOF
  22. _ERR = 020 //   
  23. };
  24. int _fillbuf(FILE *); //     ,     
  25. int _flushbuf(int, FILE *); //     ,     
  26. #define feof(p) ((p)->flag & _EOF) != 0)
  27. #define ferror(p) ((p)->flag & _ERR) != 0)
  28. #define fileno(p) ((p)->fd)
  29. #define getc(p) (--(p)->cnt >= 0 \
  30. ? (unsigned char) *(p)->ptr++ : _fillbuf(p))
  31. #define putc(x,p) (--(p)->cnt >= 0 \
  32. ? *(p)->ptr++ = (x) : _flushbuf((x),p))
  33. #define getchar() getc(stdin)
  34. #define putcher(x) putc ((x), stdout)

우리 가 자주 사용 하 는 NULL, EOF, feof (), getc () 등 은 모두 stdio. h 에서 정의 하 는 매크로 입 니 다.
다음은 버퍼 를 제어 하면
우 리 는 키보드 에서 데 이 터 를 입력 할 때 데 이 터 는 우리 가 직접 얻 은 것 이 아니 라 버퍼 에 두 었 다 는 것 을 알 고 있다. 그리고 우 리 는 버퍼 에서 우리 가 원 하 는 데 이 터 를 얻 었 다.만약 우리 가 setbuf () 나 setvbuf () 함 수 를 통 해 버퍼 를 10 개의 바이트 크기 로 설정 하고 키보드 에서 20 개의 바이트 크기 의 데 이 터 를 입력 하면 우리 가 입력 한 10 개의 데 이 터 는 버퍼 에 놓 입 니 다. 왜냐하면 우리 가 설정 한 버퍼 크기 는 10 개의 바이트 크기 의 데 이 터 를 담 을 수 있 을 뿐 20 개의 바이트 크기 의 데 이 터 를 담 을 수 없 기 때 문 입 니 다.그럼 나머지 10 바이트 크기 의 데 이 터 는 어떻게 되 나 요?잠시 입력 흐름 에 넣 었 습 니 다.아래 그림 을 보 세 요: 위의 화살표 가 표시 하 는 구역 은 입력 흐름 과 같 습 니 다. 빨간색 부분 은 하나의 스위치 와 같 습 니 다. 이 스위치 는 짙 은 녹색 구역 (버퍼 구역 표시) 에 넣 은 데 이 터 를 제어 할 수 있 습 니 다. 20 바이트 의 데 이 터 를 입력 하면 버퍼 에 10 바이트 만 넣 고 나머지 10 바이트 의 데 이 터 는 입력 흐름 에 머 물 렀 습 니 다!내 려 가서 버퍼 에 넣 으 세 요!다음 시스템 은 어떻게 이 버퍼 를 제어 합 니까?
FILE 구조 체 의 몇 가지 관련 구성원 의 의 미 를 다시 한 번 말씀 드 리 겠 습 니 다. cnct//남 은 문자 입 니 다. 버퍼 를 입력 하면 버퍼 에 ptr//다음 읽 을 문자 의 주소 base//버퍼 기본 주 소 를 읽 지 못 한 문자 가 몇 개 있 는 지 표시 합 니 다.
위 에서 우 리 는 버퍼 에 10 개의 바이트 크기 의 데 이 터 를 넣 었 습 니 다. FILE 구조 체 중의 cnct 가 10 으로 변 한 것 은 이때 버퍼 에 10 개의 바이트 크기 의 데 이 터 를 읽 을 수 있다 는 것 을 설명 합 니 다. 또한 버퍼 의 기본 주 소 는 base 가 0x00428e 60 이 라 고 가정 합 니 다. 이것 은 변 하지 않 습 니 다. 이때 ptr 의 값 도 0x00428e 60 입 니 다.0x00428e 60 이라는 위치 에서 데 이 터 를 읽 기 시작 하 는 것 을 의미 합 니 다. 버퍼 에서 5 개의 데 이 터 를 읽 을 때 cnct 는 5 로 바 뀌 었 습 니 다. 버퍼 에 5 개의 데 이 터 를 읽 을 수 있 음 을 의미 합 니 다. ptr 는 0x0042e 865 로 바 뀌 었 습 니 다. 다음 에 우리 가 5 개의 데 이 터 를 읽 을 때 cnct 는 0 으로 바 뀌 었 습 니 다.버퍼 에 데이터 가 없다 는 뜻 입 니 다. ptr 는 0x 0042869 로 바 뀌 었 습 니 다. 다음 부 터 는 이 위치 에서 버퍼 에서 데 이 터 를 읽 어야 한 다 는 뜻 입 니 다. 그러나 이 때 버퍼 에 데이터 가 없 기 때문에 입력 흐름 에 남 은 10 개의 데 이 터 를 넣 어야 합 니 다. 이렇게 버퍼 에 10 개의 데이터 가 있 습 니 다. 이때 cnct 는 10 으로 바 뀌 었 습 니 다.방금 우리 가 말 한 ptr 의 값 은 0x00428e 69 이 고 버퍼 에 데 이 터 를 다시 넣 을 때 이 ptr 의 값 은 0x00428e 60 으로 바 뀌 었 습 니 다. 이것 은 버퍼 에 데이터 가 없 을 때 ptr 라 는 값 을 새로 고침 하여 버퍼 를 가리 키 는 기본 주소 인 0x0042e 860 이라는 값 을 가리 키 기 때 문 입 니 다!다음 부 터 는 이 자리 에서 데 이 터 를 읽 어야 하기 때 문 입 니 다!
여기 서 설명 이 필요 합 니 다. 키보드 에서 문자열 을 입력 할 때 Enter 키 를 두 드 려 야 이 문자열 을 버퍼 에 보 낼 수 있 습 니 다. 그러면 두 드 린 이 Enter 키 (\r) 는 줄 바 꿈 문자 로 변 환 됩 니 다. 이 줄 바 꿈 자 는 버퍼 에 저장 되 고 문자 로 계 산 됩 니 다!예 를 들 어 우 리 는 키보드 에서 123456 이라는 문자열 을 두 드 린 다음 Enter 키 (\r) 를 두 드 려 서 이 문자열 을 버퍼 에 보 냈 다. 그러면 이때 버퍼 의 바이트 개 수 는 6 이 아니 라 7 이다.
버퍼 리 셋 은 포인터 ptr 를 버퍼 의 기본 주소 로 바 꾸 는 동시에 cnct 의 값 을 0 으로 바 꾸 는 것 입 니 다. 버퍼 리 셋 후 에는 데이터 가 없 기 때 문 입 니 다.

좋은 웹페이지 즐겨찾기