- 스터디 설명 : 에이블스쿨 교육생들과 CS 공부를 위해 자발적으로 개설 및 참여한 스터디입니다.
- 혼자 공부하는 컴퓨터 구조+운영체제를 교재로 사용하였고, 일부 내용은 별도의 자료로 공부하였습니다.
15-1. 파일과 디렉토리
파일
- 파일 : 보조기억장치에 저장된 관련 정보의 집합
- 파일은 이름과 파일을 실행하기 위한 정보, 메타데이터(metadata)로 구성된다.
- 메타데이터는 파일과 관련된 부가 정보로, 속성이라고도 한다.
- 저장하는 데이터가 늘어날수록 데이터를 저장,검색,관리하는 규약이 필요하여 등장
파일 속성과 유형
- 운영체제마다 조금씩 다르게 관리하지만, 대표적인 속성의 중료는 나음과 같다.
- 파일 유형 : 운영체제가 인식하는 파일 종류
- 크기 : 파일의 현재 크기 및 최대 크기
- 보호 : 파일 읽기, 쓰기, 실행에 대한 권한 지정
- 생성자 및 소유자
- 생성 날짜, 최근 접근 날짜, 최근 수정 날짜
- 위치
- 파일 유형을 운영체제에 알려주기 위해 가장 흔히 사용하는 방식은 확장자를 이용하는 것이다.
파일 연산을 위한 시스템 호출
- 파일을 다루는 모든 작업은 운영체제에 의해 이루어지기 때문에, 응용프로그램이 파일을 다루기 위해서는 시스템 콜을 이용해야한다.
디렉토리(directory)
- 과거 운영체제에는 하나의 디렉터리만 존재하여, 모든 파일을 같은 디렉터리에 담았다. 이러한 구조를 1단계(single-level) 디렉토리라고 부른다.
- 현재는 여러 계층을 가진 트리 구조(tree-structured) 디렉토리를 사용한다.
- 디렉토리 관련 연산 역시 운영체제를 통해 이루어지므로 시스템 콜을 사용한다.
트리 구조 디렉토리
- 최상위 디렉토리로 부터 여러 서브 디렉토리로 구성된 파일 시스템이다.
- 부모 디렉토리가 없는 최상위 디렉토리를 루트 디렉토리라고 한다.
- 디렉토리를 이용해 현재 파일의 경로(path)를 표시할 수 있다.
절대 경로와 상대 경로
- 절대 경로 : 루트 디렉토리로 부터 현재 파일에 이르기까지의 고유 경로이다.
- 일반적으로 루트 디렉토리를 나타내는 슬래쉬(
/
) 를 가장 앞에 붙여서 표현한다.
- 상대 경로 : 어떤 디렉토리를 기준으로 현재 파일에 이르기까지의 경로이다.
- 일반적으로 슬래쉬 없이 시작하거나 구두점(
.
)을 가장 앞에 붙여서 표현한다.
.
: 현재 디렉토리를 기준으로 사용
..
: 상위 디렉토리를 기준으로 사용 (슬래쉬로 구분하여 중첩 가능)
- 한 파일은 단 한 개의 절대 경로를 가지며, 기준에 따라 여러 상대 경로를 가질 수 있다.
디렉토리 엔트리
- 사실 많은 운영체제에서 디렉토리는 특별한 형태의 파일로 간주한다.
- 디렉토리 파일 내에는 디렉토리에 담겨있는 파일의 정보를 테이블 형태로 저장되어있다.
- 디렉토리 엔트리에는 디렉토리가 담고 있는 파일의 위치를 유추할 수 있는 정보를 담고 있으며, 종종 파일 속성을 명시하기도 한다.
15-2. 파일 시스템
파일 시스템은 파일과 디렉토리를 보조기억장치에 일목요연하게 저장하고 접근 할 수 있도록 하는 운영체제의 내부 프로그램이다.
파티셔닝과 포매팅
- 한 번도 사용된적 없는 보조기억장치를 사용하기 위해서는 파티셔닝과 포매팅 작업을 거쳐야 한다.
- 파티셔닝(Partitioning) : 보조기억장치에 논리적인 영역을 나누는 작업
- 파티셔닝을 통해 나누어진 논리적 디스크를 파티션이라고 한다.
- 파티션을 여러개 생성하면 각 파티션별로 운영체제를 설치하거나 데이터를 설치할 수 있다.
- 나누어진 파티션을 합치는 작업 역시 가능하다.
- HDD에서는 운영체제 파티션과 데이터 파티션을 나눌 경우 데이터를 안전하게 보관하면서 운영체제를 재설치할 수 있고, 속도 향상을 꾀할 수 있어 파티셔닝이 거의 필수였으나, SSD에서는 성능 향상의 이점이 없고, 현대 운영체제는 재설치가 간편하기 때문에 파티셔닝을 반드시 할 필요는 없다.
- 포매팅(formatting) : 보조기억장치에 데이터를 저장할 수 있도록 파일 시스템을 설정하는 작업이다.
- 사용할 파일 시스템 결정 (FAT16, FAT32 등)
- 일반적으로 포매팅 과정에서 저장장치를 초기화 한다.
- 포매팅에는 저수준 포매팅(물리적 포매팅)과 논리적 포매팅이있다.
- 저수준 포매팅 : 하드디스크의 물리적 섹터를 하나하나 없애는 방식이다. 주로 공장에서 사용하는 물리적 포매팅과정이다.
- 논리적 포매팅 : 일반적으로 FAT의 경우 보조기억장치의 파일을 NULL로 덮어 씌우는 것을 통해 초기화하는 포매팅 방식이다. 데이터 자체를 지우지 않고 NULL로 간주하는 것이기 때문에 복구가 가능하다.
파일 할당 방법
- 운영체제는 파일과 디렉토리를 블록 단위로 읽고 쓴다.
- HDD의 가장 작은 단위는 섹터이지만, 모든 섹터를 일일히 관리하게에는 수가 너무 많기 때문에 블록단위로 묶는다.
- 윈도우에서는 블록 대신 ‘클러스터’라는 용어를 사용한다.
- 각 블록에 파일을 할당하는 방법에는 연속 할당과 불연속 할당이 있다.
- 불연속 할당은 다시 연결 할당과 색인 할당으로 나눌 수 있다.
연속 할당 방법
- 연속 할당은 연속 페이지 할당 방식과 동일하게 파일을 연속적인 블록에 계속 할당하는 것이다.
- 이렇게 저장했을 경우 파일의 첫 저장 주소와 블럭 길이만 알면 파일에 접근할 수 있다.
- 그러나 연속 페이지 할당 방식처럼 외부 단편화를 야기한다는 문제가 있다.
연결 할당(linked allocation)
- 연결 할당은 모든 블록을 연속할당 하지 않고, 각 블록의 일부에 다음 블록의 주소를 저장하여 다음 블록을 찾아갈 수 있도록 한다.
- 마지막 블록에는 더이상 블록이 없다는 특별한 표시자를 사용한다.
- 그 외에 디렉토리 엔트리에 파일 길이를 저장함으로써 파일을 덜 읽거나 더 읽는 문제를 막을 수 있다.
- 연결 할당은 연속 할당 방법의 외부 단편화 문제를 해결하지만 다음과 같은 문제가 있다.
- 파일을 처음부터 순차적으로 접근해야 한다. → 임의의 위치에 접근하는 것이 느림
- 중간 블록에 문제가 생기면 해당 블록 이후의 블록은 모두 접근할 수 없다.
- 이러한 단점을 해결하기 위해 연결 할당을 변형한 FAT 파일 시스템을 사용한다.
색인 할당(indexed allocation)
- 파일의 모든 블록 주소를 색인 블록이라는 하나의 블록에 모아 관리하는 방식
- 인덱스에 따라 파일을 접근할 수 있어 임의의 i번째 위치에 빠르게 접근할 수 있다.
- 디렉토리 엔트리에 색인 블록 주소를 저장하여 찾는다.
- 파일의 블록 중 일부가 손상되어도 색인 블록을 통해 나머지 블록에 접근할 수 있다.
- 유닉스 파일 시스템이 색인 할당을 기반으로 한 파일 시스템이다.
파일 시스템
FAT 파일 시스템
- 다음 블록의 주소를 저장하는 기존 연결 할당 방식에서 파일 할당 테이블(FAT; File Allocation Table)을 추가한 형태이다.
- 파일 할당 테이블에는 다음 블록의 주소들이 하나로 모여 테이블 형태로 저장되어 있다. (일종의 전역 변수)
- FAT에는 각 블록별로 다음 블록 주소가 저장된다.
- 파일의 일부 블록에 문제가 발생하더라도 FAT를 통해 다음 블럭을 찾을 수 있다.
- FAT16, FAT32와 같이 뒤에 붙는 숫자는 하나의 블록을 표현하기 위한 비트 수를 뜻한다.
- FAT는 일반적으로 파티션의 앞부분에 만들어지며, 실행 도중 메모리에 캐시 될 수 있다. → 임의 접근 속도 향상
- FAT에서 디렉토리 엔트리는 담고있는 파일의 이름과 첫 번째 블록 주소를 저장한다.
- 루트 디렉토리부터 접근하고자 하는 파일의 디렉토리 엔트리 위치까지 탐색
- 파일이 있는 디렉토리 위치에서는 첫 블록 주소부터 FAT를 참조하여 다음 블록으로 접근
- 주로 저용량 저장 장치용 파일 시스템으로 많이 이용된다.
유닉스 파일 시스템
- i-node라는 색인 블록에 파일 블록의 위치를 저장하는 색인 할당 시스템
- i-node도 파티션 내 특정영역에 모여있다.
- i-node 블록 하나는 기본적으로 15개의 블록 주소를 저장할 수 있다.
- 파일의 블록 수가 이보다 클 경우 순차적으로 더 많은 블록을 저장할 수 있는 방법을 사용한다.
- 15개의 저장 가능 수 중 12개 까지는 직접 블록 주소를 저장한다.
- 12개로 부족할 경우 13번 주소에 단일 간접 블록 주소를 저장한다.
- 단일 간접 블록 : 파일 데이터가 저장된 블록 주소를 가리키는 블록
- 여전히 부족할 경우 14번 주소에 이중 간접 블록 주소를 저장한다.
- 단일 간접 블록 여러개를 이용하고, 각 단일 간접 블록의 주소를 가리키는 이중 간접 블록 주소를 저장
- 여전히 부족하다면 15번 주소에 삼중 간접 블록 주소 저장
유닉스 파일 시스템에서 블록 하나의 크기는 지정이 가능하며 일반적으로 1~8KB를 사용한다.
블록 하나의 크기가 4KB라 할 경우 직접 주소는 4KB, 단일 간접 주소는 4MB, 이중 간접 주소는 4GB, 삼중 간접 주소는 4TB 정도의 데이터를 저장할 수 있다.
간접 블록 포인터 하나의 크기는 일반적으로 4KB이다.
- 유닉스 파일 시스템의 디렉토리에는 파일 이름과 i-node 번호가 저장되고, i-node는 앞서 말한 방법으로 블록 주소를 저장한다.
기타 파일 시스템
윈도우 - NTFS (NT 파일 시스템)
리눅스 - ext 파일시스템
저널링 파일 시스템
- 기존 파일 시스템에서는 파일 시스템 변경 도중 예기치 못한 이유로 컴퓨터가 강제로 종료되면(시스템 크래시) 파일 시스템이 훼손될 수 있다.
- 기존에는 이를 방지하기 위해 파일 검사 및 복구 시스템을 복구 직후 실행하였다. 다만 이는 모든 블록에 대한 검사를 진행해야 했기에 많은 시간을 필요로 한다.
- 저널링 파일 시스템은 저널링 기법을 통해 시스템 크래시가 발생했을 때 파일을 빠르게 복구한다.
- 파티션에 로그 영역을 두어 작업 직전 항상 변경사항에 대한 로그를 남긴다.
- 작업이 종료되면 로그를 삭제한다.
- 만약 작업이 종료되지 않은 채 시스템 크래시가 발생하면 로그가 남아있는지 여부를 통해 파일의 문제를 찾고 복구가 가능하다.
- 현대 파일 시스템은 대부분 저널링 기능을 지원한다.
마운트
- 마운트 작업이란 파일 시스템을 편입 시키는 작업을 의미한다.
- 유닉스 파일 시스템에 FAT 파일 시스템을 가진 USB를 연결했을 경우, 마운트 작업을 통해 USB 파일에 접근할 수 있게 된다.
- USB에 있던 루트 디렉토리가 마운트한 경로의 최상단에 위치하게 된다.
PE헤더
- PE란 Portable Executable File Format의 약자이다.
- 파일을 다른 이식 가능한 다른 곳에 옮겨도 실행 가능하도록 만들어 놓은 포맷
- PE 파일은 윈도우OS에서 사용되는 실행파일 형식을 의미한다.
- PE 파일에는 실행 파일을 실행하기 위한 정보가 기록된 PE 헤더가 저장되어있다.
PE 파일의 종류
- 실행 계열 : EXE, SCR
- 라이브러리 계열 : DLL, OCX, CPL, DRV
- 드라이버 계열 : SYS, VXD
- 오프젝트 파일 계열 : OBJ
PE 파일의 구조
- PE는 여러 구조체로 구성되어있으며 종류가 매우 많다.
- 섹션 데이터 사이에는 Null 값이 존재하는데 이는 PE 파일이 Offset으로 위치를 표현하기 때문에 각 섹션의 시작위치가 기본 단위의 배수이어야 하므로, 그 사이에 있는 빈공간은 Null로 채우기 때문이다.
PE 헤더
e_magic
: 현재 파일이 PE 파일인지 체크하는 용도로 사용됨
- 값이
4d 5a
(MZ)라면 PE 파일임을 나타낸다.
e_flanew
: IMAGE_NT_HEADER
가 어느 위치에 있는지 표시하는 변위(offset)값
DWORD Signature
: 현재 파일이 PE 파일인지 체크하는 용도로 사용
PE\0\0
을 표시한다.
- 과거 바이러스 제작자들이 자신의 값을 표시하는데 주로 사용하였으나, 현재는 이 값이 변조되어있을 경우 파일이 실행되지 않도록 조치한다.
파일을 실행하기 위한 가장 기본적인 데이터가 담겨있다.
Machine
: 어떤 CPU에서 이 파일이 실행될 수 있는지 표시
NumberOfSection
: 섹션의 수를 명시
- 일반적으로 .txt / .rdata / .data / .rsrc로 4개의 섹션이 존재한다.
TimeDataStamp
: 파일을 빌드한 날짜를 명시
SieOfOptionalHeader
: PE 구조체를 로딩하기 위한 IMAGE_OPTIONAL_HEADER32
의 크기를 명시
Characteristics
: 현재 파일의 형식을 명시 (DLL과 EXE 구분)
PE 구조체중 중요한 값을 가장 많이 담고 있는 헤더
Magic
: 32비트와 64비트를 구분하는 표식
SizeOfCode
: 코드의 전체 크기를 가리킨다.
MajorLinkerVersion
, MinorLinkerVersion
: 빌드 시 어떤 버전의 컴파일러를 사용했는지 명시
ImageBase
: 파일이 실행될 경우 가상 메모리에 올라가는 번지
- exe 파일의 경우 별도의 옵션이 없으면 0x4000000이 된다.
AddressOfEntryPoint
: 실제 파일이 메모리에서 실행되는 시작 지점
BaseOfCode
: 실제 코드가 실행되는 번지
ImageBase
에 BaseOfCode
를 더한 값이 코드 영역이 시작되는 주소이다.
SizeOfHeaders
: PE 헤더의 크기를 명시
Subsystem
: 이 프로그램이 GUI인지 CLI인지 명시하는 필드