파일을 액세스 하기 위해서는 몇 가지 개념을 이해해야 합니다. 첫 번째가 파일 디스크립터(File discriptor)로 어떤 프로세스가 open 한 파일을 명명해 주는 ID입니다. 사용자가 설정하지 않아도 open 되는 파일이 존재합니다. standard input/output/error로 각각 0번, 1번, 2번 discriptor를 받습니다.
그다음부터 열리는 파일의 경우 3번 file discriptor를 받습니다. 즉 discrpitor는 프로세스가 오픈한 파일들에 대해서 순차적으로 부여된 id로 기본적으로 0, 1, 2가 사용되기 때문에 3번부터 시작이 됩니다. 파일 디스크립터 외에도 C의 standard library를 통해서 파일을 액세스 할 수 있습니다.
이 경우 파일 스트림, 파일 포인터라고 하는 data structure에 대한 포인터를 얻어야 합니다. 이전 포스터에서 언급한 stdin, stdout, stderr가 data structure에 대한 파일 포인터입니다.
이번에는 파일 포인터에 대해서 알아볼 것인데 위에서 말한 파일 스트림을 의미할 때의 파일 포인터와는 다른 개념입니다. 파일은 byte sequence를 가지고 있는 entity로 볼 수 있습니다. 이런 파일에서 우리가 특정 바이트를 읽을려면 특정 바이트로 포인터를 이동시켜야 합니다. 이때 이동하는 포인터가 파일 포인터입니다.
파일 포인터 값을 이동시킬 때는 lseek() system call 오퍼레이션을 사용하면 됩니다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main() {
char *fname = "data.txt";
int fd;
off_t fsize;
if ((fd = open(fname, O_RDONLY)) < 0) {
fprintf(stderr, "open error for %s\n", fname);
exit(1);
}
if ((fsize = lseek(fd, 0, SEEK_END)) < 0) {
fprintf(stderr, "lseek error\n");
exit(1);
}
}
이 C코드에서는 if문에서 open system call을 사용하여 read only로 data.txt 파일을 오픈합니다. 이러면 open의 return 값으로 data.txt 파일의 파일 디스크립터 ID가 반환됩니다. 코드 상에서 제일 처음 오픈한 파일이니 파일 디스크립터 ID는 3이 됩니다.
이후 data.txt 파일의 제일 뒷부분을 읽기 위해서 lseek을 사용하여 SEEK_END(끝부분)으로 옮깁니다. lseek의 return값은 옮겨서 간 새로운 파일 포인터의 위치입니다. (파일의 사이즈로도 볼 수 있습니다.)
디렉터리 트리 상에 위치하는 파일을 오픈하여 특정 데이터를 읽어오는 과정에 대해서 자세히 알아보겠습니다. 그러려면 우선 사용자가 부여한 symbolic file name을 OS가 이해하는 형태인 ID로 바꿔줘야 합니다. 이 ID를 통해서 메타 데이터로 이동을 합니다. (ID가 메타 데이터를 액세스 할 수 있는 인덱스와 같음)
이렇게 파일의 이름을 ID로 변환하는 과정을 flie name parsing이라고 부릅니다. file name parsing이 시작되는 점은 디렉터리가 됩니다. 어떤 디렉토리 밑에 파일들이 여러 개 존재한다면 파일마다 파일 이름이 있고 internel 하게 사용되는 ID가 존재합니다.
unix os에서는 디렉터리도 파일로 인식합니다. 이 디렉토리 파일에는 디렉터리에 있는 파일 이름과 그 파일의 ID의 fair로 구성된 레코드들이 들어 있습니다. 파일을 액세스 하고 싶으면 파일을 포함하고 있는 디렉터리로 가서 해당 파일의 ID를 얻어오면 됩니다. 이때 ID는 파일 디스크립터에 대한 인덱스라고 생각하면 됩니다.
파일 디스크립터는 파일 콘텐츠와 함께 디스크에 존재합니다. 파일을 액세스할 때 파일 컨텐츠 주소 정보가 파일 디스크립터에 있으니 파일 디스크립터는 메인 메모리를 복사한 상태로 볼 수 있습니다. 파일 디스크립터에는 파일의 크기, 생성된 시간, 소유자나 그룹의 아이디 또는 protection bit 같은 것들이 저장되어 있습니다.
OS를 통해서 파일 데이터를 얻어오려면 symbolic file name을 파일 디스크립터 인덱스로 바꿔 파일 디스크립터를 얻어오면 파일의 콘텐츠가 저장되어 있는 주소를 얻을 수 있습니다. (데이터를 액세스 할 수 있는 상태)
파일 디스크립터를 예전에는 일정 영역에 어레이 형태로 만들었는데 이 경우 파일 콘텐츠와 파일 디스크립터 상의 디스크 암 움직임이 많이 일어났습니다. 그래서 어레이 형태로 모아두지 않고 파일 컨텐츠 주변에 모아 seek time을 줄이는 형태로 발전합니다. (파일 디스크립트와 해당하는 파일 콘텐츠끼리 붙어두는 형태, 파일 디스크립터 = PCB 같은 느낌?)
unix OS에서 파일 콘텐츠를 액세스 하기 위해서는 파일 디스크립터를 액세스해야 합니다. 이 내부에 데이터 콘텐츠의 주소가 들어 있기 때문입니다. unix에서는 이 파일 디스크립터를 index node의 약자인 inode라고 부릅니다. (파일의 ID는 inumber라고 부릅니다.)
file name parsing에 대해서 정리해 보겠습니다. 다음과 같이 root / a / b / c 이런 형태로 c 파일이 존재한다고 해보겠습니다. 이때 c 파일의 inumber를 얻어와야 합니다. 기본적으로 OS가 부팅 단계에서 root 파일에 대한 inumber와 inode를 알고 있습니다. (보통 root의 inumber는 2입니다.)
그래서 2라는 inumber를 통해 메인 메모리에 있는 inocde를 얻어옵니다. 이 inode를 통해서 root directory file의 데이터를 읽어올 수 있습니다. 이를 통해 a라는 디렉터리의 inumber를 얻을 수 있습니다. a의 inumber를 통해 a라는 디렉토리의 inode를 읽어와 a 디렉토리 콘텐츠 정보에서 b의 inumber를 얻을 수 있습니다. (이걸 c파일의 inode까지 반복)
absolute path name(root부터 해당 파일까지)가 주어진다면 root 디렉터리부터 차근차근 파싱 하여 액세스 하고자 하는 파일의 inode를 얻을 수 있습니다. 이런 absolute path name은 각 파일이 unique name을 부여해 주는 역할을 합니다.
working directory에 대해 알아보겠습니다. 워킹 디렉터리는 파일 시스템에서 작업을 할 때 그 작업이 이루어지는 디렉토리를 말합니다. 워킹 디렉토리는 absolute full path name이 아닌 relative path name을 사용할 수 있게 해줍니다. (cmd나 ubuntu 같은 경우 현재 작업 중인 디렉토리를 기준으로 시작할 수 있음)
파일 시스템은 root로부터 시작되는 디렉토리 트리라고 할 수 있습니다. 하지만 OS 입장에서는 이 디렉토리 트리가 모두 매핑된 스토리지 구조가 파일 시스템이 됩니다. 그래서 OS에게는 파일 시스템이란 스토리지 상에 포맷된 잘 정렬된 조직 구조로 볼 수 있습니다.
unix system에서는 file system을 mount 시킨다는 개념이 존재합니다. window의 경우 파일 시스템이 다르다면 그걸 전부 눈으로 확인할 수 있습니다. (파일 시스템이 존재하는 볼륨이 c../ , b../ 이렇게 표현이 됩니다.)
unix는 하나의 파일 시스템 트리밖에 보이지 않습니다. 여러 개의 파일 시스템을 동시에 가질 수 있지만 그 파일 시스템을 포함하고 있는 볼륨들은 전부 사라지고 기존 파일 시스템에 별도로 존재하는 파일 시스템을 mount를 통해 붙일 수 있습니다.
위 사진 속에 /home/users 밑에 다른 파일 시스템을 붙여버리는 작업을 진행하는 명령어를 볼 수 있습니다.
'CS > Operating System' 카테고리의 다른 글
27. File Structures (0) | 2024.02.04 |
---|---|
26. File System (0) | 2024.02.03 |
24. Device Drivers (2) | 2024.01.31 |
23. I/O Device 관리 (1) | 2024.01.30 |
22. Trends in Memory Management (1) | 2024.01.29 |