pintos 10

PintOS의 메모리에 관한 공부

Pintos에서 메모리 할당 전략은 주로 페이지 단위로 이루어지며, 물리 메모리와 가상 메모리 시스템을 효과적으로 관리하기 위한 다양한 기법을 사용합니다.1. 커널 메모리 할당 (Kernel Memory Allocation)Pintos의 커널은 페이지 단위로 메모리를 할당합니다. 이는 운영 체제 자체가 사용하는 메모리나 커널 내에서 필요로 하는 메모리를 할당하는 과정에서 이루어집니다.페이지 할당 (Page Allocation): 커널은 palloc_get_page()와 같은 함수로 물리 메모리에서 페이지를 할당합니다. 이 함수는 물리 메모리에서 사용할 수 있는 페이지를 찾아 반환하며, 페이지는 일반적으로 4KB 크기의 고정된 메모리 블록입니다.프레임 할당 (Frame Allocation): 페이지는 물리..

WIL/스터디 2024.09.10

File System

파일 시스템의 경우 FAT 부분과 파일/디렉토리로 나뉘어져 있습니다. 파일과 디렉토리 내용에 관해서는 이미 우리가 OS를 사용하면서 써왔기 때문에 친숙한 개념이라 생각하여 생략하고, FAT와 Inode 아키텍쳐에 관한 설명과 저희가 어떤 식으로 파일시스템을 구현했는지를 정리했습니다.  기존의 Pintos는 freemap을 사용한 형태로 디스크를 사용하고 있습니다. freemap은 bitmap이라고 이해하시면 됩니다. 그래서 기존의 파일 시스템은 그림과 같이 단편화가 발생해 있으면 Data가 들어갈 수 없습니다. 따라서 우리는 disk를 효율적으로 사용하기 위해 bitmap에서 fat 방식으로 파일시스템을 수정하게 됩니다. FAT란 File Allocate Table의 약자로 빈 Sector를 찾아 데이터..

Copy on Write (CoW)

Project 3의 Extra 과제인 Copy on Write에 관해 알아보겠습니다. 먼저, Git book에서는 copy on write에 대해 다음과 같이 정의하고 있습니다.  그래서 fork를 할 때에는 새로운 물리 페이지를 할당하지 않고 부모와 같은 물리 페이지를 매핑만 해주었다가 추후에 write를 시도할 때에만 새로운 물리 페이지를 할당해 주면 되는 것입니다. 우리는 filebacked Page의 경우에 이미 같은 물리 메모리를 공유하도록 구현했기 때문에 여기서 힌트를 얻을 수 있었습니다. 기존에 우리 프로그램은 이 페이지가 작성가능한지만을 검사하고 있었습니다. 그런데 이 페이지가 원래 부모 프로세스가 만들어 놓은 Anonymous Page이고 fork된 프로세스에서 write 하려고 한다면 ..

System Call

User Program 주의 주 개념인 System Call을 핀토스에서 어떻게 처리하는 지에 대해 간략하게 알아보았습니다.  먼저 System Call이 어떻게 동작하는지 대략적으로 그려보았습니다. 유저 모드에서 동작을 하고 있던 프로세스가 read나 write같은 함수에서 system call을 호출 시 syscall entry shell을 통해 현재 CPU의 동작하던 내용을 user stack에 저장한 후 커널로 넘어가게 됩니다. 그 후 syscall_handler에서 system call 함수를 실행하고, ret를 통해 다시 유저 모드로 돌아와 작업을 재개합니다.  유저 함수에서 어떠한 동작을 하다가 system call을 호출하는 경우가 발생할 수 있습니다. Pintos에서는 저희가 유저 함수를..

Multi-Level Feedback Queue Scheduler

핀토스 1주차 Option 과제인 Advanced Scheduler를 구현해봤습니다. 기존의 Priority Scheduler의 경우에는 우선 순위가 낮은 스레드가 오랫동안 CPU를 점유하지 못하는 문제가 발생할 수 있습니다. 이로 인해 스레드의 평균 반응 시간이 너무 길어지는 문제가 발생합니다. 이를 해결 하기 위한 방법으로 multi-level feedback queue scheduler가 제시되었습니다. MLFQS는 Priority에 따라 여러 개의 Ready Queue가 존재하고, Priority에 영향을 주는 변수가 있어서 Feedback으로 Priority를 조절할 수 있습니다. 이 때, multi level까지는 구현하기 힘들 것 같아서 Feedback만 구성을 해봤습니다. 사실 상 feed..

Pintos의 Test Case는 완벽하지 않다

Pintos의 test를 맹신하지 마라. Test를 실행하다가 이상한 부분을 발견했는데 2번째 msg에서 실제로 값에 접근하지 않았는 데 VA가 정확히 ACTUAL로 부터 4096만큼 떨어진 곳에 위치한 곳에 ACTUAL + 4096이 있는 것을 발견했다.확인해 보니 실제로 프로그램은 ACTUAL + 4096을 할당해주긴 하지만 접근을 하지않아 page fault조차 뜨지 않았다. 이는 말이 안된다고 판단해서 내 코드를 계속 뜯어보다가 나중에 Test Case를 열어보게 되었다.#define ACTUAL ((void *) 0x10000000)voidtest_main (void){ int handle; void *map; CHECK ((handle = open ("sample.txt")) > 1, "..

왜 환경 별로 Test 결과가 다를까?

같은 Pintos Code를 갖고 EC2와 Docker, WSL에서 각각 다른 Result 가 나오는 경우가 있다. 이는 기본적으로 환경 별로 처리 속도가 다르기 때문인데 단적인 예시로 내 Docker 환경에서는 1초에 2.1억번 정도 loop가 수행된다.// DockerCalibrating timer... 209,715,200 loops/s. 그런데 같은 팀원의 환경에서 돌려본 결과 EC2는 1.3억번, WSL에서 돌려본 결과는 3.1억번 정도가 수행된다.// EC2Calibrating timer... 129,638,400 loops/s// WSLCalibrating timer... 314,163,200 loops/s. 이 때문에 보통 프로그램이 허술하면 EC2에서는 아무런 문제없이 도는데 Doc..

Syscall Entry Shell 내용을 뜯어보자

syscall_entry.S는 시스템콜이 호출되었을 때 user mode에서 작동하고 있던 프로세스를 kernel mode로 이동하여 시스템 콜을 수행하고 다시 ret하기까지 수행하는 shell 파일이다.// syscall-entry.S#include "threads/loader.h".text.globl syscall_entry.type syscall_entry, @functionsyscall_entry: movq %rbx, temp1(%rip) movq %r12, temp2(%rip) /* 저장된 레지스터 호출 */ movq %rsp, %rbx /* Store userland rsp */ movabs $tss, %r12 movq (%r12), %r1..

MLFQS를 구현함에 있어 All List에 관하여 (feat. dangling pointer)

먼저 사전에 알아야 하는 점이 있다. 바로 Pintos 학습자료가 32bit와 64bit로 나뉘어져 있다는 것이다. 아직까지 일부분만 학습하여 32bit와 64bit Pintos의 차이를 전부 알지는 못하지만 thread부분에서 체감할 수 있는 부분이 있었다.바로 all_list가 없다는 것. 이 페이지는 내가 학습한 내용이 너무 방대하여 만들었지만, 현재의 나도 정글의 선배 기수들의 자료들을 많이 참고하며 공부하고 있는데, 언젠가 다른 정글러들이 mlfqs를 구현하고자 하다가 헤메면서 꽁꽁 숨겨져있는 이 page까지 왔다면 아마 이러한 연유로 찾아오지 않았을까 하는 생각이 든다. 만약 MLFQS가 mlfqs-load-1 테스트는 성공했는데 mlfqs-load-60에서 잘 돌다가 120초에서 뜬금없이 에..

Thread.c에서 Context Switching 함수 분석을 해보자

다음 함수는 CPU Register를 흉내내어 만들어져 있는 구조체에서 %rsp를 포인터로 사용해 CPU Register로 올리는 함수이다.// thread.cvoid do_iret(struct intr_frame *tf) { /* Structure -> CPU Register로 데이터 이동 (Load) */ __asm __volatile( // 입력한 그대로 사용 "movq %0, %%rsp\n" // 인자 *tf의 주소를 RSP에 저장 이 때, %0을 처음보게 되어 무슨 뜻인지 몰랐었는데, 이는 input operands로 들어온 0번째 인자를 가리키게 되며 컴파일러는 먼저 가서 확인 한 후 돌아와 할당하게 된다. "movq 0(%..