Subject | Done |
스레드 | ✔ |
사용자 프로그램 | ✔ |
가상 메모리 | |
파일 시스템 |
📌 프로젝트 이해하기
Introduction
- 프로젝트 1에서는 커널 내의 특정한 기능을 만들어, 테스트 코드를 커널에 직접 컴파일하여 확인했음
- 프로젝트 2에서는 사용자 프로그램을 실행하여 운영 체제를 테스트할 것
- ifdef VM은 프로젝트 3에서 구현할 가상 메모리 관련이므로, 해당 블록을 건드리거나 그 안에 코드를 작성하지 말 것
- 과제 들어가기 전에 '동기화', '가상주소' 개념에 대해 배우고 들어갈 것
Synchronization
- 동기화를 구현하는 가장 간단한 방법은 인터럽트를 비활성화 하는 것
- 즉 CPU가 인터럽트에 응답하지 못하도록 일시적으로 차단하는 것
- include/threads/synch.h: 세마포어, 락, 모니터 관련 작업
- 모든 동기화 문제는 인터럽트를 끄면 쉽게 해결 가능, 인터럽트가 꺼져 있는 동안에는 동시성이 없으므로 경쟁 조건이 발생하지 않기 때문
- 하지만 대부분의 동기화 문제를 세마포어, 잠금 및 조건 변수를 사용하여 해결할 것
- 인터럽트 비활성화 방법은 커널 스레드와 인터럽트 처리기 간에 공유되는 데이터를 조정할 때 유일하게 사용됨
- 인터럽트 핸들러는 잠들 수 없기 때문에 잠금을 획득할 수 없음, 이때만 인터럽트를 꺼 커널 스레드 내에 보호되도록 할 것
Virtual Address
63 48 47 39 38 30 29 21 20 12 11 0
+-------------+----------------+----------------+----------------+-------------+------------+
| Sign Extend | Page-Map | Page-Directory | Page-directory | Page-Table | Physical |
| | Level-4 Offset | Pointer | Offset | Offset | Offset |
+-------------+----------------+----------------+----------------+-------------+------------+
| | | | | |
+------- 9 ------+------- 9 ------+------- 9 ------+----- 9 -----+---- 12 ----+
Virtual Address
Using the File System
- 내부 동기화 없음, 동시 액세스는 서로 간섭함, 동기화를 사용하여 한 번에 하나의 프로세스만 파일 시스템 코드를 실행하도록
- 파일 크기는 생성 시 고정, 루트 디렉토리는 파일로 표시되므로 생성할 수 있는 파일 수도 제한됨
- 파일 데이터는 단일 익스텐트로 할당됨, 즉 단일 파일 데이터는 디스크의 연속 섹터 범위를 차지해야 함, 따라서 시간이 지남에 따라 파일 시스템이 사용되므로 외부 조각화는 심각한 문제가 될 수 있음
- 하위 디렉토리 없음, 파일명은 14자로 제한
- 작업중 시스템 충돌이 발생하면 자동으로 복구 X, 디스크 손상 가능성 있음
Virtual Memory Layout
- 핀토스의 가상 메모리는 사용자 가상 메모리와 커널 가상 메모리의 두 영역으로 나뉨
- 사용자 가상 메모리는 가상 주소 0에서 KERN_BASE까지, 커널 가상 메모리는 그 나머지 부분을 차지함
- 사용자 가상 메모리는 프로세스 단위, 커널이 한 프로세스에서 다른 프로세스로 전환할 때 사용자 가상 주소 공간도 전환함
- 스레드 구조체에는 프로세스의 페이지 테이블에 대한 포인터가 포함되어 있음
- 커널 가상 메모리는 global, 실행 중인 사용자 프로세스나 커널 스레드에 관계없이 항상 같은 방식으로 매핑됨
- User Program은 자신의 사용자 가상 메모리에만 액세스할 수 있음
- 커널 스레드는 커널 가상 메모리와 프로세스의 사용자 가상 메모리에 모두 액세스할 수 있음
- 하지만 커널에서도 매핑되지 않은 사용자 가상 주소로 메모리에 액세스하려고 시도하면 페이지 오류 발생함
User Stack
Fake return address
- Entry function(시작 함수)은 돌아갈 주소가 없지만, 다른 함수와의 포맷을 맞추기 위해 fake return address를 가짐
- 핀토스는 유저 프로세스 생성 후 자식 프로세스 종료시까지 무한 대기
- 인터럽트 프레임 = 구조체
- 이전에 실행하던 프로세스의 컨텍스트(context)를 저장하기 위함
📌 프로젝트 파고들기
Todo | Done |
Argument Passing | ✔ |
User Memory Access | ✔ |
System Calls | ✔ |
Process Termination Message | ✔ |
Deny Write on Executables | ✔ |
Extend File Descriptor |
Argument Passing
목표: process_exec() 함수의 사용자 프로그램 파라미터 설정
- Caller는 스택에 다음 명령어의 주소를 푸시하고 Callee의 첫 번째 명령어로 점프함
- Callee에게 반환값이 있을 경우 레지스터 RAX에 저장함
- Callee는 스택에서 반환 주소를 Pop하고 지정된 위치로 점프하여 반환함
Program Startup Details
- 스택 Top에 단어를 놓음, 포인터를 통해 참조되므로 순서는 중요하지 않음
- 오른쪽에서 왼쪽으로 스택의 각 문자열과 널 포인터 센티넬의 주소를 푸시함
- 단어 정렬을 위해, 첫번째 푸시 전에 스택 포인터를 8의 배수로 반올림
- 마지막으로 가짜 리턴주소를 반환, 엔트리 함수는 절대 반환되지 않지만 스택 프레임은 다른 것과 동일한 구조여야 함
- 현재는 새 프로세스에 대한 인수 전달을 지원하지 않음
- process_exec()에서 단순히 파일명을 인수로 사용하는 대신 공백을 이용하여 단어를 나누도록 확장해야 함
- 첫번째 단어는 프로그램명, 두번째 단어부터 파라미터 나열
- process_exec("grep foo bar")라고 하면, 두 인수 foo와 bar를 전달하여 grep을 실행
- 또한 명령줄에서 여러 공백은 단일 공백과 동일, 즉 여러줄 명령어로 실행되어야 함
User Memory Access
- 목표 : 잘못된 메모리에 대한 접근 제한
- System Call을 구현하려면 사용자 가상 주소 공간에서 데이터를 읽고 쓰는 방법을 제공해야 함
- System Call의 Parameter로 제공된 포인터에서 데이터를 읽을 때 이 기능이 필요
1) 프로세스 종료 조건
- Null Pointer이거나
- Kernel VM을 가르키거나 (kern_base 보다 값이 크다는 것과 같은 의미)
- mapping되어 있지 않은 VM을 가르키거나 (할당되지 않은 주소)
2) pml4 테이블
- 페이지 디렉터리 포인터 테이블 최대 512개 관리 가능
- 사용자 가상 주소에 해당하는 커널 가상 주소 반환
- 매핑되지 않은 주소일 경우 null 포인터 반환
System Calls
- 목표 : 시스템 콜 및 시스템 콜 핸들러 구현
- userprog/syscall.c에서 System Call 핸들러를 구현할 것
- syscall 명령은 System Call하는 데 가장 일반적으로 사용되는 수단, Pintos에서는 사용자 프로그램이 이 syscall을 호출함
- %rax는 system call 번호이며, 네번째 파라미터는 %rcx가 아닌 %r10
시스템 콜 사용 이유
- 어플리케이션이 OS의 중요 데이터를 수정/삭제하는 걸 막기 위해
- 직접적인 HW 관련 요청은 OS가 제공하는 시스템콜을 통하도록
- 유저 어플리케이션이 시스템콜 호출 시 해당 어플은 커널 모드로 전환됨
Process Termination Message
- 사용자 프로세스가 호출되거나 다른 이유로 종료될 때마다 프로세스의 이름과 종료 코드를 다음 형식으로 print할 것
- 프로세스의 전체 이름이어야 할 것, 사용자 프로세스가 아닌 커널 스레드 관련이나 다른 메세지는 print하지 말 것
Deny Write on Executables
- 실행 파일로 사용 중인 파일에 대한 쓰기를 거부하는 코드를 추가할 것
- 프로세스가 디스크에서 변경되는 도중에 코드를 실행하려고 하면 예측할 수 없는 결과가 발생하기 때문
- file_deny_write(), file_allow_write() 사용하여 파일 쓰기 권한을 제어하면 됨
Extend File Descriptor
1) File Descriptor Table
- File Table을 가르키는 포인터들의 집합
- 프로세스가 현재 사용중인 파일들을 관리함
- 프로세스마다 하나씩 가지고 있음
- fd가 이들의 index 역할을 함
2) File Table
- 프로세스에 의해 열린 파일의 R/W을 지원
- 파일이 열릴 때마다 하나씩 할당
- 프로세스가 같은 파일을 3번 열면, 이 프로세스의 File Table Entry가 3개 생성된다는 의미
3) VFS Inode Table
- 프로세스들이 사용하고 있는 파일의 i-node를 담고 있는 테이블
- i-node: i-node 번호, 파일 종류, 권한, 크기, 데이터 블록을 가르키는 포인터 등
'그냥 하기 > in the 정글' 카테고리의 다른 글
[정글] WEEK 13 | 핀토스 끝까지 가보자고 (0) | 2023.11.05 |
---|---|
[정글] WEEK 11-12 | 대충 핀토스 지겹다는 제목 (0) | 2023.11.05 |
[정글] WEEK 08 | 오고야 말았다 핀토스 (0) | 2023.11.05 |
[정글] WEEK 07 | 웹서버 만들기 (1) | 2023.11.03 |
[정글] WEEK 06 | 그니까 Malloc Lab이 뭔데 (0) | 2023.11.03 |