책/CSAPP

CSAPP 10

에린_1 2024. 2. 24. 01:04
728x90

CSAPP

10. 시스템 수준 입출력(System - Level I/O)

  • 입출력은 메인메모리와 네트워크, 디스크 같은 외부장치들 간에 데이터를 복사하는 작업이다. 입력연산은 입출력 장치에서 메인메모리로 복사하고, 출력연산은 데이터를 메모리에서 디바이스로 복사한다.

왜 UNIX I/O를 배워야 하는가?

  • UNIX I/O를 이해하면 다른 시스템 개념을 이해하는데 도움이 된다.
  • 때로는 UNIX I/O 이외의 다른 방법이 없을 수도 있다.

10.1 Unix I/O

  • 리눅스에서 파일은 연속된 m개의 바이트다.
  • 네트워크, 디스크, 터미널 같은 모든 I/O 디바이스들은 파일로 모델링되며, 모든 입력과 출력은 해당 파일을 읽거나 쓰는 형식으로 수행된다. Unix I/O를 통해 모든 입력과 출력이 일정하고 통일된 방식으로 수행되도록 해준다.

파일열기

  • 응용은 I/O 디바이스에 접근하겠다는 의도를 해당 파일을 열겠다고 커널에 요청하는 방법으로 알린다. 커널은 식별자(Descriptor)라고 하는 작은 비음수를 리턴하며, 이것은 이후의 파일에 관한 모든 연산에서 이 파일을 나타낸다. 커널은 열린 파일에 관한 모든 정보를 추적한다. 응용은 식별자만을 추적한다.

현재 파일 위치의 변경

  • 커널은 파일을 열 때마다 파일 위치 k를 관리하며, 이것은 처음에는 0이다. 파일위치는 파일의 시작 부분에서부터의 바이트 오프 셋이다. 응용프로그램은 seek 연산을 수행해서 현재의 파일 위치를 명시적으로 설정할 수 있다.

파일 읽기와 쓰기

  • 읽기 연산은 현재 파일 위 k에서 시작해서 n>0 바이트를 파일에서 메모리로 복사하고, k를 n증가시킨다. 크기가 m바이트인 파일이 주어졌을 때, k≥m 인 읽기연산을 수행하면 end-of-file(EOF)라고 알려진 조건이 발생하며, 응용프로그램에서 감지할 수 있다. 마찬가지로, 쓰기 연산은 현재 파일 위치 k에서 시작해서 n>0바이트를 메모리에서 파일로 복사하고, k를 갱신한다.

파일닫기

  • 응용이 파일 접근을 끝마치면, 커널에 파일을 닫아줄 것을 요청한다. 커널은 파일을 열었을 때, 만든 자료구조들을 반환하는 것으로 대응하며, 식별자를 가용식별자 풀로 복원한다 프로세스가 어떤 이유에서든 종료할 때, 커널은 모든 열려있는 파일들을 닫고, 이들의 메모리 자원을 반납한다.

10.2 파일

  • 각각의 리눅스 파일은 시스템에서의 역할을 나타내는 타입을 가진다.
    • 일반 파일은 임의의 데이터를 포함한다.
    • 디렉토리는 링크들의 배열로 구성되며, 각각의 파일 이름을 파일로 대응시키며, 이 이름은 또 다른 디렉토리일 수도 있다. 각각의 디렉토리는 최소 두 개의 항목을 포함한다 : (점 한 개)은 자신의 디렉토리로의 링크이고 ..(점 두 개)는 디렉토리 계층구조에서 부모 디렉토리로의 링크다.
    • 소켓은 네트워크상의 다른 프로세스와 통신하기 위해 사용되는 파일이다.
  • 리눅스 커널은 파일들을 루트 디렉토리라고 하는 /(사선)에 연결된 단일 디렉토리 계층구조로 구성된다.
  • 시스템에서 각 파일은 루트 디렉토리의 직접 또는 간접적인 후손들이다.
  • 자신의 컨텍스트의 일부로, 각 프로세스는 현재 작업 디렉토리를 가지며, 이것은 디렉토리 계층구조 내에서 자신의 현재 위치를 나타낸다.
  • 디렉토리의 계층구조에서의 위치는 경로 이름 pathnames로 명시한다.
    • 절대 경로 이름
    • 상대 경로 이름

10.3 파일 열기와 닫기

  • 프로세스는 open 함수를 호출해서 기존의 파일을 열거나 새 파일을 생성한다.
  • open 함수는 file name을 파일식별자 변환하고 식별자 번호를 리턴한다.
  • 마지막으로, 프로세스는 오픈한 파일을 close 함수를 호출해서 닫는다. 이미 닫은 파일 식별자를 닫게 되면 에러다.

10.4 파일 읽기와 쓰기

  • read 함수는 식별자의 현재 파일 위치에서 최대 n바이트를 메모리 위치 buf로 복사한다. 리턴 값 01은 에러를 0은 EOF를 나타낸다. 그렇지 않으면 리턴 값을 실제로 전송한 바이트수를 나타낸다.
  • write 함수는 메모리 위치 buf에서 식별자 fd의 현재 파일 위치로 최대 n바이트를 복사한다.
  • 일부 경우에 read와 write는 응용이 요청하는 것보다 더 적은 바이트를 전송한다. 이러한 짧은 카운터는 에러를 나타내는 것은 아니다. 이들은 여러 이유로 발생한다.
    • EOF를 읽기 중에 만났을 때
    • 터미널에서 텍스트 줄을 읽을 때
    • 네트워크 소켓을 읽거나 쓸 때

10.5 RIO 패키지를 이용한 안정적인 읽기와 쓰기

  • RIO(Robust I/O) 짧은 카운터를 자동으로 처리한다. RIO 패키지는 짧은 카운트가 발생할 수 있는 네트워크 프로그램 같은 응용에서 편리하고, 안정적이고, 효율적인 I/O를 제공한다. RIO 패키지는 두 가지 서로 다른 종류의 함수를 제공한다.
    • 버퍼 없는 입력 및 출력 함수 : 메모리와 파일 사이에 응용 수준의 버퍼링없이 직접 데이터를 전송한다. 이들은 특히 네트워크에서 바이너르 데이터를 읽고 쓸 때 유용하다.
    • 버퍼를 사용하는 입력 함수 : 텍스트 라인들과 내용이 응용 수준 버퍼에 캐시되어있는 파일의 바이너리 데이터를 효율적으로 읽도록 해주며, 이것은 printf와 같이 표준 I/O 함수를 위해 제공되는 것과 유사하다.

10.6 파일 메타 데이터 읽기

  • 응용은 파일에 관한 정보를 stat과 fstat 함수를 호출해서 가져올 수 있다.
  • stat함수는 파일의 이름을 입력으로 받아서 stat 구조체의 멤버들을 채워준다. fstat 함수도 비슷하지만 파일 이름 대신 파일 식별자를 사용한다.

10.7 디렉토리 내용 읽기

  • 응용은 readdir 계열의 함수를 이용해서 디렉토리의 내용을 읽을 수 있다.
  • opendir 함수는 경로의 이름을 받아서 디렉토리 스트림을 가리키는 포인터를 리턴한다. 스트림은 항목들의 정렬된 리스트에 대한 추상화다
  • readdir를 호출하면 dirp 스트림에서 다음 디렉토리 항목으로의 포인터를 리턴하거나 만일 더 이상 항목이 없는 경우 NULL을 리턴한다.
  • closedir 함수는 스트림을 닫고 자신의 지원들을 반환한다.

10.8 파일 공유

  • 커널은 세 개의 관련 자료구조를 사용해서 오픈한 파일들을 표현한다.
    • 식별자 테이블(descriptor table) : 각 프로세스는 자신만의 별도의 식별자 테이블을 가지고 있으며, 이들의 엔트리는 프로세스의 오픈된 파일 식별자로 인덱스 된다. 각 오픈 식별자 엔트리는 파일 테이블 내의 한 개의 엔트리를 가진다.
    • 파일 테이블(file table) : 오픈 파일들은 모든 프로세스들이 공유하는 한 개의 파일 테이블로 표시된다. 각 파일 테이블 엔트리는 현재 파일 위치, 현재 가리키고 있는 식별자 엔트리들의 참조 횟수, v-노드 테이블의 엔트리로의 포인터로 구성된다. 식별자를 닫으면 관련 파일 테이블 엔트리에서 참조 횟수를 감소시킨다. 커널은 파일 테이블 엔트리를 자신의 참조 횟수가 0이 될 때 까지 지우지 않는다.
    • v-노드 테이블(v-node table) : 파일 테이블 처럼 v-노드 테이블은 모든 프로세스와 공유된다.
  • 각각의 식별자가 자신의 고유 파일 위치를 가지며, 따라서 다른 식별자에 대한 서로 다른 읽기 작업은 파일내의 다른 위치로부터 데이터를 가져올 수 있다.

10.9 I/O 재지정

  • 리눅스 쉘은 표준 입력 및 출력을 디스크 파일과 연결할 수 있도록 해주는 I/O 재지정 연산자를 제공한다.

10.10 표준 I/O

  • C언어는 표준 I/O 라이브러리라고 부르는 고급 입력 및 출력 함수의 집합을 정의하고 있으며, 이들은 UNIX I/O 고급 대체 함수를 프로그래머에게 제공한다. 라이브러리는 파일을 열거나 닫고, 바이트를 읽거나 쓰고 스트림을 읽거나 쓰고 복잡한 포맷을 갖는 I/O를 위한 함수를 제공한다.

10.11 종합 : 어떤 I/O 함수를 이용해야 하는가?

  • 기본 가이드
    • G1 : 가능하면 표준 I/O 함수를 사용하라
    • G2 : 이진 파일을 읽을 때는 scanf나 rio_readlineb를 이용하지 말아라. 두 가지 함수는 텍스트 파일을 읽기 위해 특별히 만든 것이다.
    • G3 : 네트워크 소켓에 대한 I/O를 위해서는 RIO함수들을 이용하라.
728x90

' > CSAPP' 카테고리의 다른 글

CSAPP 12  (1) 2024.02.24
CSAPP 12.6 - 12  (0) 2024.02.21
CSAPP 12.4 - 12.5  (0) 2024.02.20
CSAPP 12-12.3  (0) 2024.02.19
CSAPP 11  (1) 2024.02.18