어떻게 영속 장치를 관리하는가? API는 어떤 것이있고, 구현의 중요한 측면은 무엇인가.
Abstractions for Storage
‼️저장 장치의 가상화에 대한 두가지 주요 개념 개발
- File
- 단순히 읽거나 쓸 수 있는 순차적인 바이트의 배열
- 각 파일은 low-level의 이름을 갖고 있다. (inode number)
- 운영체제는 파일의 구조를 모른다.(어떤 파일이 그림인지, 문서인지,,등)
- Directory
- (user-readable name, low-level name) 쌍으로 이루어진 목록을 가짐
- low-level의 이름을 갖고 있다. (inode number)
File System Interface
- Creating files/directories
- Accessing files/directories
- Removing files/directories
Creating Files
open 시스템 콜을 호출하면서 O_CREAT 플래그를 전달하면 프로그램은 새로운 파일을 만들 수 있다.
int fd = open("foo",O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR|S_IWUSR);
O_CREAT: 파일이 존재하지 않으면 생성한다.
**O_WRONLY: 쓰기 전용으로 연다.
O_TRUNC: 파일이 이미 존재하면, 파일 크기를 0바이트로 잘라 기존 내용 제거
S_IRUSR | S_IWUSR: 권한을 지정한다. 이 경우 소유자가 읽고 쓸 수 있도록 한다.**
File descriptor ⇒ open의 return 값이 들어감
- 프로세스마다 존재하는 정수, UNIX 시스템에서 파일을 접근하는데 사용된다.
- open된 파일을 읽고 쓰는 데 사용된다, 물론 해당 파일에 대한 권한을 갖고 있어야한다. ⇒ 이런 측면에서 file descriptor는 capability
- 특정 동작에 대한 수행 자격을 부여하는 핸들이다.
- 파일 디스크립터를 파일 객체를 가르키는 포인터로 볼 수 있다.
Accessing Files (Sequential) ⇒ 순차적 읽기
prompt> echo hello > foo
prompt> cat foo
hello
prompt>
cat을 사용하여 파일의 내용을 화면에 덤프 echo의 출력을 파일 foo로 전송
이제 cat프로그램은 어떻게 파일 foo에 접근하는지 알아보자
prompt> strace cat foo
...
open("foo", O_RDONLY|O_LARGEFILE) = 3
read(3, "hello\\n", 4096) = 6
write(1, "hello\\n", 6) = 6
hello
read(3, "", 4096) = 0
close(3) = 0
...
prompt>
strace : 프로그램이 호출하는 시스템콜을 추적하고, 그 결과를 화면에 보여준다. 옆의 결과는 strace가 보여준 결과이다.
왜 open은 3을 return 했냐? 프로세스가 이미 세개의 파일을 열어 놓아서 !
- 표준 입력 0
- 표준 출력 1
- 표준 에러 2
Accessing Files (Random)
운영체제는 현재 오프셋을 추적하여 다음 읽기, 쓰기 위치를 결정한다.
오프셋은 두가지 중 하나의 방법으로 갱신
- Implicit update N바이트를 읽거나 쓸 때 현재 오프셋 N이 더해진다.
- Explicit updatewhencea SEEK_SET 이면 오프셋은 offset 바이트로 설정된다. whecea SEEK_CUR이면, 오프셋은 현재 위치에 offset 바이트를 더한 값으로 설정 whencea SEEK_END 이면, 오프셋은 파일의 크기에 offset 바이트를 더한 값으로 설정
- off_t lseek(int fd, off_t offset, int whence);
Open File Table
시스템에서 현재 열려 있는 모든 파일
- 테이블의 각 항목:
- 파일 디스크립터가 참조하는 기본 파일
- 현재 오프셋 (파일에서 현재 읽기 또는 쓰기가 진행 중인 위치)
- 파일의 읽기 및 쓰기 가능 여부 등의 관련 세부 사항을 추적
struct {
struct spinlock lock;
struct file file[NFILE];
} ftable;
struct file {
int ref;
char readable, writable;
struct inode *ip;
uint off;
};
unique entry
- 각 파일은 열린 파일 테이블에 고유한 항목을 가진다.
- 다른 프로세스가 동시에 같은 파일을 읽더라도, 각 프로세스는 열린 파일 테이블에 자신의 엔트리를 가진다.
- 파일의 논리적인 읽기 또는 쓰기 작업은 독립적으로 이루어진다.
Shared File Entries
fork()
int main(int argc, char *argv[]) {
int fd = open("file.txt", O_RDONLY);
assert(fd >= 0);
int rc = fork();
if (rc == 0) {
rc = lseek(fd, 10, SEEK_SET);
printf(“C: offset %d\\n", rc);
} else if (rc > 0) {
(void) wait(NULL);
printf(“P: offset %d\\n", (int) lseek(fd, 0, SEEK_CUR));
}
return 0;
}
dup()
기존 파일 디스크립터와 동일한 기본 열린 파일을 참조하는 새 파일 디스크립터를 생성
새로운 디스크립터는 사용되지 않은 가장 낮은 번호의 파일 디스크립터를 사용
- 출력 리디렉션에 유용
int fd=open(“output.txt", O_APPEND|O_WRONLY);
close(1);
dup(fd); //duplicate fd to file descriptor 1
printf(“My message\\n");
• dup2(), dup3()
Writing Immediately
write()
파일 시스템은 쓰기 작업을 일정 시간 동안 메모리에 버퍼링한다. ⇒ 즉시 쓰기가 완료된 것 처럼 보임 나중에 쓰기 작업이 실제로 저장 장치에 발행
fsync()
파일 시스템이 모든 더티 데이터(아직 디스크에 기록되지 않은 데이터)를 강제로 디스크에 쓴다.
Removing Files
unlink()
Making Directories
mkdir() : 새로운 디렉토리를 생성
디렉토리가 생성되면 처음 빈 상태, 기본적인 내용만.(자기자신, 부모 디렉터리)
. : 디렉토리 자신을 가리킵니다.
.. : 부모 디렉토리를 가리킵니다.
prompt> ls -a
Reading Directories
ls 동작 과정
opendir(), readdir(), closedir() 을 사용
int main(int argc, char *argv[]) {
DIR *dp = opendir(".");
struct dirent *d;
while ((d = readdir(dp)) != NULL) {
printf("%lu %s\\n", (unsigned long) d->d_ino, d->d_name);
}
closedir(dp);
return 0;
}
struct dirent {
char d_name[256]; // filename
ino_t d_ino; // inode number
off_t d_off; // offset to the next dirent
unsigned short d_reclen; // length of this record
unsigned char d_type; // type of file
};
Deleting Directories
Mechanisms for Resource Sharing
Abstraction of a process
CPU virtualization -> private CPU Memory virtualization -> private memory
File system
디스크 가상화 -> 파일과 디렉토리 파일은 종종 다른 사용자와 프로세스 간에 공유되며, 프라이빗하지 않다. Permission bits
Permission Bits
Making a File System
mkfs 명령어는 주어진 디스크 파티션에 빈 파일 시스템을 작성한다. 빈 파일 시스템은 루트 디렉토리부터 시작
prompt> mkfs -t ext4 /dev/sda1
파일 시스템 트리 내에서 접근 가능하도록 해야 함
Mounting a File System
mount 명령어는 기존 디렉토리를 대상 마운트 포인트로 사용하여, 새로운 파일 시스템을 해당 디렉토리 트리에 붙여넣는다.
prompt> mount -t ext4 /dev/sda1 /home/users
예를 들어, /home/users/ 경로가 새로 마운트된 디렉토리의 루트를 가리키게 됨
[출처]
https://github.com/remzi-arpacidusseau/ostep-translations/blob/master/korean/README.md
ostep-translations/korean/README.md at master · remzi-arpacidusseau/ostep-translations
Various translations of OSTEP can be found here. Help the cause and contribute! - remzi-arpacidusseau/ostep-translations
github.com
해당 책을 기반으로 정리하였습니다.
'Computer Science' 카테고리의 다른 글
[OSTEP 운영체제 정리] - Log-Structured File System (0) | 2024.06.24 |
---|---|
[OSTEP 운영체제 정리] - File system implementation (0) | 2024.06.24 |
[OSTEP 운영체제 정리] - IO and HDD (0) | 2024.06.24 |
[OSTEP 운영체제 정리] - Concurrency Problem (0) | 2024.06.24 |
[OSTEP 운영체제 정리] - semaphore (0) | 2024.06.23 |