-
[WEEK08] 정글 5기 - 정글 끝까지(PintOS) - Threads정글 크래프톤 5기 회고 및 정리/WIL 2024. 5. 9. 18:32
- 아래 공부 키워드 참조검색어
Project 0: PintOS
1. Virtual Machine ~= Hypervisor - 가상 머신은 소프트웨어로 구현된 가상 컴퓨터
- 하이퍼바이저는 가상 머신을 만들고 관리하는 소프트웨어qemu - 가상화 및 에뮬레이션 소프트웨어 에뮬레이션 - 하드웨어나 소프트웨어의 동작을 소프트웨어적으로 모방하여 다른 환경에서 동작하도록 하는 기술 2. Common bugs Memory leak - 프로그램이 동적으로 할당한 메모리를 제대로 해제하지 않고 계속해서 사용하지 않는 메모리 블록을 차지하는 상황 Race Condition - 아래 공부 키워드 참조 Deadlcok - 아래 공부 키워드 참조 Use after free - 프로그램이 이미 해제된 메모리를 사용하려고 할 때 발생한다. Project 1: Threads
1. Time-sharing system ● Context Swtiching - 아래 공부 키워드 참조 ● Scheduler - 아래 공부 키워드 참조 ○ Round Robin(RR) - 아래 공부 키워드 참조 ○ Priority ■ Priority donation ○ Multi-Level Feedback
Queue Scheduler (MLFQS)- 아래 공부 키워드 참조 ■ 4BSD - 아래 공부 키워드 참조 ■ nice - 아래 공부 키워드 참조 ● Thread - 아래 공부 키워드 참조 ○ Thread control block (TCB) - 아래 공부 키워드 참조 2. Timer Interrupt 3. Timer sleep 4. Synchronization ● Semaphore - 아래 공부 키워드 참조 ● lock ● condvar - 조건 변수(Condition Variable)의 줄임말이다.
- 조건 변수는 동기화 매커니즘 중 하나로, 스레드 간의 통신과 동기화를 위해 사용된다.
- 조건 변수는 일반적으로 뮤텍스와 함께 사용된다.
- 뮤텍스는 임계 구역에 대한 접근을 보호하기 위해 사용되고, 조건 변수는 특정 조건이 충족될 때까지 대기하고 있는 스레드들을 꺠워주는 역할이다.
1. wait(condition_variable, mutex)
· 조건 변수가 만족되지 않으면 현재 스레드를 블록하고 뮤텍스를 해제한다.
· 다른 스레드가 조건 변수를 신호(signal) 또는 브로드캐스트(broadcast)하여 현재 스레드를
깨울 때까지 대기한다
2. signal(condition_variable)
· 대기 중인 스레드 중 하나를 꺠운다.
· 어떤 스레드가 꺠어날지 모른다.
공부 키워드
1. Process, Thread
Program - 컴퓨터에서 실행할 수 있는 파일을 아직 실행하지 않은 상태 : 정적 프로그램 & 프로그램 Process - 독립적으로 실행되는 프로그램의 인스턴스로, 자체적인 주소 공간, 메모리, 데이터 스택 및 다른 시스템의 자원을 갖는다.
자원공유
- 각 프로세스는 독립적인 메모리 공간과 시스템 자원을 가지므로, 프로세스간 자원 공유는 IPC(Inter-Process Communication) 매커니즘을 통해 이뤄진다.프로세스의
자원구조
- 코드 영역 (Code /Text)
· 개발자가 작성한 프로그램 함수들의 코드가 CPU가 해석 가능한 기계어 형태로 저장
- 데이터 영역
· 전역 변수 및 각종 데이터
- 스택 영역
· 지역 변수와 같은 호출한 함수가 종료되면 되돌아올 임시적인 자료를 저장하는 독립적인 공간
- 힙 영역
· 생성자, 인스턴스와 같은 동적으로 할당되는 데이터들을 위해 존재하는 공간
* 프로세스의 4가지 메모리 영역(Code, Data, Heap, Stack) 중 스레드는 Stack만 할당받아 복사하고 Code, Data, Heap은 프로세스 내의 다른 스레들과 공유된다.프로세스의
자원공유1. IPC(Inter-Process Communication)
2. LPC(Local inter-Process Communication)
3. 별도로 공유 메모리를 만들어서 정보를 주고받도록 설정PCB
(Process
Control
Block)- 운영체제에서 프로세스를 관리하기 위해 해당 프로세스의 상태 정보를 담고 있는 자료구조
- 프로세스 스케줄링을 위해 프로세스에 관한 모든 정보를 저장하는 임시 저장소

- 포인터(Pointer) : 프로세스의 현재 위치를 저장
- 프로세스 상태(Process state)
- 프로세스 아이디(PID)
- 프로그램 카운터 : 프로세스를 위해 다음 명령어의 주소를 포함하는 카운터 저장
- 레지스터 : CPU 레지스터에 있는 정보
- 메모리 제한 : 운영체제에서 사용하는 메모리 관리 시스템에 대한 정보
- 열린 파일목록 : 프로세스를 위해 열린 파일 목록Thread - 프로세스 내부의 실행 흐름 단위로, 프로세스의 자원과 주소 공간을 공유하면서 실행된다.
자원 공유
- 쓰레드는 같은 프로세스 내의 쓰레드들은 코드, 데이터 및 시스템 자원을 공유한다.TCB
(Thread
Control
Block)- 각 스레드마다 운영 체제에서 유지하는 스레드에 대한 정보를 담고 있는 자료구조
- TCB는 PCB안에 있다.
2. CPU Scheduling 알고리즘
프로세스 상태 
- 생성(New)
· 프로세스가 생성되고 아직 준비가 되지 않은 사앹
- 준비(Ready)
· 프로세스가 실행을 위해 기다리는 상태
· CPU를 할당받을 수 있는 상태이며, 언제든지 실행될 준비가 되어있다.
- 실행(Running)
· 프로세스가 CPU를 할당받아 실행되는 상태
- 대기(Waiting)
·프로세스가 특정 이벤트(입출력 요청 등)가 발생하여 대기하는 상태
· CPU를 할당받지 못하며, 이벤트가 발생하여 다시 Ready 상태로 전환될 때까지 대기한다.
- 종료(Terminated)
·프로세스가 실행을 완료하고 종료된 상태
· 더 이상 실행될 수 없으며, 메모리에서 제거되게 된다.프로세스 상태 전이 - Admitted
· 프로세스 생성을 승인 받음
- Dispatch
· 준비 상태에 있는 여러 프로세스들 중 하나가 스케줄러에 의해 실행됨
- Interrupt
· Timeout, 예기치 않은 이벤트가 발생하여 현재 실행 중인 프로세스를 준비 상태로 전환하고
해당 작업을 먼저 처리
- I/O or event wait
· 실행 중인 프로세스가 입출력이나 이벤트를 처리해야 하는 경우,
입출력이나 이벤트가 끝날 때까지 대기상태로 전환
- I/O or event completion
· 입출력이나 이벤트가 모두 끝난 프로세스를 다시 준비 상태로 만들어 스케줄러에 의해 선택될 수 있는 상태로 전환CPU Scheduling
알고리즘- 운영체제는 CPU 스케줄링을 통해 Ready Queue에 있는 어떤 프로세스에 CPU를 할당할 것인지 결정한다.
- 크게 선점형과 비선점형으로 나눌 수 있다.선점형 - 선점 스케줄링은 높은 우선순위의 프로세스가 들어올 경우
· 현재 프로세스를 중지시키고, 높은 우선순위의 프로세스를 처리비선점형 - 비선점 스케줄링은 한번 할당하면 끝날 때까지 다른 프로세스가 들어오지 못하게 한다. CPU 스케줄링 종류 FCFS - (First Come First Serve) / [ 비선점형 ]
- Ready Queue에 도착한 순서에 따라 CPU를 할당하는 기법
- 공평성은 유지되지만 짧은 작업이 긴 작업을, 중요한 작업이 중요하지 않은 작업을 기다림
- 장점
· 자원의 효율성이 높음
- 단점
· 평균 응답 시간이 길어진다.
· Convoy 효과 : 몇 개의 시간 걸리는 프로세스로 인해 전체 OS가 느려지는 현상SJF - (Shortest Job First) / [ 비선점형 ]
- 실행시간이 가장 짧은 프로세스에 먼저 CPU를 할당하는 기법
- 가장 적은 평균 대기 시간을 제공하는 최적의 알고리즘
- 장점
· 평균 응답 시간을 최소화할 수 있다.
- 단점
· 실행 시간이 긴 프로세스는 CPU를 할당받지 못하고 무한히 대기하는 현상 발생 (starvation)
· 해결 방법으로 aging 사용 : 오래된 작업의 우선순위를 높여주는 방식
- HRN(Highest Response ratio)
· SJF를 보완하는 알고리즘, 우선순위 계산 결과값이 높으면 우선 순위를 부여SRTF - (Shortest Remaining time First) / [ 선점형 ]
- 새로운 프로세스가 도착할 때마다 새로운 스케줄링이 이루어진다.
- 현재 실행 중인 프로세스의 남은 시간과 대기 큐에 프로세스의 실행시간이 가장 짧은 프로세스에게 CPU를 할당하는 기법
- 비선점 기법인 SJF를 선점 형태로 변경한 기법
- 단점
· 잦은 선점으로 인한 Context switching 부담, starvation의 위험RR - (Round Robin) / [ 선점형 ]
- 각 프로세스는 동일한 크기의 할당 시간을 갖게 된다.
- 할당 시간이 지나면 프로세스는 선점 당하고 Ready Queue의 제일 뒤로 간다.
- Time slice가 높다면?
· 설정한 할당 시간이 너무 커지면 FCFS와 같아진다.
- Time slice가 낮다면?
· 반대로 너무 작아지면 스케줄링 알고리즘의 목적에는 이상적이지만 잦은 Context switching으로 overhead 발생Priority
Scheduling- 우선순위가 가장 높은 프로세스에게 CPU 할당
- 선점형 스케줄링 방식
· 더 높은 우선순위의 프로세스가 도착하면 실행중인 프로세스를 멈추고 CPU를 선점
- 비선점형 스케줄링 방식
· 더 높은 우선순위의 프로세스가 도착하면 Ready Queue의 Head에 넣음Multilevel
Queue
Scheduling
- 우선순위에 따른 준비 큐가 여러 개의 큐들로 나뉘고 각각의 큐는 각자의 스케줄링 알고리즘을 가지고 있다.
- 우선순위가 높은 큐부터 처리되기 떄문에 낮은 큐의 프로세스가 처리가 안되는 Starvation 현상이 나타날 수 있다.
- 각 큐 사이에서 프로세스들이 이동할 수 없어서 유연성이 떨어진다.3. Semaphore와 Mutex
Semaphore 
- 임계 구역에 여러 스레드가 들어갈 수 있고, counter를 두어서 허용 가능한 스레드를 제한하는 기법
- 공유된 자원의 데이터 혹은 임계영역(Critical Section) 등에 여러 Process 혹은 Thread가 접근하는 것을 막아준다.
· 즉, 동기화 대상이 하나 이상
- 일반적으로 비교적 긴 시간을 확보하는 리소스에 대해 이용하게 된다.
- 유닉스 시스템의 프로그래밍에서 세마포어는 운영체제의 리소스를 경쟁적으로 사용하는 다중 프로세스에서 행동을 조정하거나 또는 동기화 시키는 기술이다.
- 세마포어는 운영체제 또는 커널의 한 지정된 저장장치 내 값으로, 각 프로세스는 이를 확인하고 변경할 수 있다.Mutex 
- 임계 구역에 1개의 스레드만 들어갈 수 있는 동기화 기법
- 공유된 자원의 데이터 혹은 임계영역(Critical Section) 등에 하나의 Process 혹은 Thread가 접근하는 것을 막아준다.
· 즉, 동기화 대상이 하나
- Critical Section을 가진 쓰레드들의 Running Time이 서로 겹치지 않게 각각 단독으로 실행되게 하는 기술이다.
- 즉, 쉽게 말하면 뮤텍스 객체는 두 쓰레드가 동시에 사용할 수 없다는 의미이다.Mutex VS Semaphore 1. 세마포어는 뮤텍스가 될 수 있지만, 뮤텍스는 세마포어가 될 수 없다.
· 뮤텍스는 상태가 0, 1 두 개뿐인 binary Semaphore
2. 세마포어는 소유할 수 없는 반면, 뮤텍스는 소유가 가능하며 소유주가 이에 대한 책임을 진다.
· 뮤텍스의 경우 상태가 두개 뿐인 Lock이므로 lock을 가질 수 있다.
3. 뮤텍스의 경우 뮤텍스를 소유하고 있는 쓰레드가 이 뮤텍스를 해제할 수 있다.
· 하지만 세마포어의 경우 이러한 세마포어를 소유하지 않는 쓰레드가 세마포어를 해제할 수 있다.
4. 세마포어는 시스템 범위에 걸쳐있고 파일 시스템상의 파일 형태로 존재한다.
· 반면 뮤텍스는 프로세스 범위를 가지며 프로세스가 종료될 때 자동으로 clean up ehlsek.
* 가장 큰 차이점은 관리하는 동기화 대상의 갯수이다.
· 뮤텍스는 동기화 대상이 오직 하나뿐일 때
· 세마포어는 동기화 대상이 하나 이상일 때 사용한다.Critical Section - 다중 프로그래밍 운영체제에서 여러 프로세스가 데이터를 공유하면서 수행될 때 각 프로세스에서 공유 데이터를 접근(Access)하는 프로그램 코드 부분을 가리키는 말이다.
- 공유 데이터를 여러 프로세스가 동시에 엑세스하면 시간적인 차이 등으로 인하여 잘못된 결과를 만들어 낼 수 있기 때문에 한 프로세스가 위험 부분을 수행하고 있을 때
- 즉, 공유 데이터를 액세스하고 있을 때는 다른 프로세스들은 절대로 그 데이터를 액세스하지 못하도록해야 한다.4. Race Condition
Race Condition - 두 개 이상의 concurrent한 프로세스(혹은 스레드)들이 하나의 자원(리소스)에 접근하기 위해 경쟁하는 상태
- 예방 방법
· 세마포어와 뮤텍스Mutual exclusion - Race Condition을 막기 위해 두 개이상의 프로세스가 공용 데이터에 동시에 접근해야 하는 것을 막아야 한다.
- 한 프로세스가 공용 데이터를 사용하고 있으면, 다른 프로세스가 그 자원을 사용하지 못하도록 막는 것.
- 제어 문제 발생
· Deadlock
· StarvationDeadlock - 프로세스가 각자 프로그램을 실행하기 위해 두 자원 모두 엑세스 해야 한다고 가정할 때,
· 프로세스는 두 리소스를 사용하여 프로그램을 수행할 때까지 소유한 리소스를 해제하지 않는다.Starvation - 프로세스들이 더 이상 진행하지 못하고 영구적으로 블록되어 있는 상태
· 시스템 자원에 대한 경쟁 도중에 발생할 수 있고, 프로세스 간의 통신 과정에서도 발생할 수 있다.Deadlock &
Starvation- Deadlock은 리소스에 대한 경쟁으로 인해 모든 프로세스가 블록된 상태
- Starvation은 특정 프로세스가 리소스를 얻을 수 없어서 영원히 대기하는 상황5. Deadlock
Deadlock (교착상태) - 두 개 이상의 프로세스와 스레드가 서로 자원을 기다리면서 무한히 기다리게 되는 상태
- 교착 상태는 두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있기 때문에, 다음 단계로 진행하지 못하는 상태Deadlock 발생 조건 - 상호배제
· 한 자원에 대한 여러 프로세스의 동시 접근은 불가능
- 점유와 대기
· 하나의 자원을 소유하고 다른 프로세스 혹은 스레드 자원 요청
- 비선점
· 다른 프로세스에 할당된 자원은 사용이 끝날 때까지 강제로 빼앗을 수 없음
- 환형 대기
· 프로세스의 집합에서 순환 형태로 자원을 대기Deadlock 해결 방법 - 예방
· 교착 상태 발생 조건 중 하나를 제거하면서 해결, 시스템의 효율성이 떨어지는 단점 존재
- 회피
· 교착 상태에 빠질 가능성이 있는지 확인 후 자원할당
- 탐지
· 교착 상태 발생을 허용 후 탐지를 한다.
- 복구
· 프로세스 종료, 자원 선점6. Context Switching
Context
Switching- CPU가 다음 우선순위의 프로세스 실행을 위해 Context를 저장하고 다음 실행을 위해서 Context를 교체하는 작업
- 구체적으로, 동작 중인 프로세스가 대기하면서 해당 프로세스의 상태를 보간하고, 대기하고 있던 다음 순서의 프로세스가 동작하면서 이전에 보관했던 프로세스의 상태를 복구하는 작업을 말한다.
- 즉, 컨텍스트 스위칭을 하는 주체는 스케줄러이다.Context - CPU가 해당 프로세스를 실행하기 위해 해당 프로세스의 정보들 Context
Switching
Overhead
- PCB 저장 및 복원 비용
- CPU 캐시 메모리 무효화에 따른 비용
- 프로세스 스케줄링 비용7. Multi-Level Feedback Queue Scheduler (MLFQS)
Multi-Level Feedback
Queue Scheduler (MLFQS)- 라운드 로빈에 업그레이드된 알고리즘
- MLFQ 는 기본적으로 CPU 사용률과 I/O 사용률이 좋게 나오는 작은 크기의 Time Slice를 선택한다.
- CPU Bound Process 들에게는 Time Slice를 크게 준다.
- CPU Bound Process와 I/O Bound Process를 구분 방법은 CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 CPU 사용이 적은거니 I/O Bound Process일 확률이 높다.
- 반대로 Time Slice 크기를 오버하면 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황이면 CPU Bound Process일 확율이 높다.
- 이러한 아이디어로 우선순위 큐를 여러 개 두고
· 우선순위가 높으면 타임슬라이스가 작고 우선순위가 낮을수록 타임슬라이스 크기가 커진다.
- 만약 CPU를 뺏기는 상황에는 우선순위가 더 낮은 큐로 이동한다.
· 다음 실행 때 타임 슬라이스가 커진다.
* CPU Bound Process : 대부분의 시간을 CPU 작업에 사용하는 프로세스
· CPU 사용률과 처리량 중시
* I/O Bound Process : 대부분의 시간을 I/O 작업에 사용하는 프로세스
· 응답속도 중시4BSD - 4BSD(Berkeley Software Distribution)
- 인터랙티브 프로세스 우선순위 향상
· 사용자와의 상호작용이 필요한 프로세스는 빠른 반응 시간이 중요
· 4BSD 스케줄러는 이러한 프로세스가 자주 CPU를 양보하는 경향을 감지하고 그들의 우선순위 상승
- 백그라운드 작업 우선순위 감소
· CPU 사용량이 매우 높은 프로세스는 시스템의 전반적인 반응성에 영향을 줄 수 있다.
· 이러한 프로세스의 우선순위는 시간이 지남에 따라 점차 감소하여,
인터랙티브 프로세스에게 CPU 사용 기회를 더 많이 제공nice - 프로세스의 우선순위를 조정하는 데 사용되는 값
- nice 값은 사용자가 프로세스의 기본 우선순위를 조정할 수 있게 해주며, 이 값은 프로세스의 우선순위에 직접적인 영향을 미침
- nice 값의 범위 : -20 ~ 19
· 낮은 값은 높은 우선순위를 의미하고, 높은 값은 낮은 우선순위를 의미한다. 기본 값은 0
- nice 값의 사용
· 사용자는 nice 명령어를 사용하여 실행 중이거나 새로 시작하는 프로세스의 nice 값을 설정 가능
출처
더보기1. 프로세스와 스레드
2. CPU 스케줄러 알고리즘
3. Race condition & Mutex & Semaphore
https://iredays.tistory.com/125
4. MLFQS
ETC..
1. 응용 프로그램을 구현할 때 multiprocess와 multithread 중 하나를 선택하는 기준은 어떤 것이 있는지 몇 가지 제시하시오
안전성 vs 자원 사용 - 시스템의 안정성이 매우 중요한 경우, 멀티 프로세스가 선호된다.
- 리소스가 제한적인 환경에서는 멀티스레드가 더 효율적일 수 있다.구현의 복잡성 - 스레드는 공유 메모리로 인해 동기화 문제가 복잡해질 수 있으므로 개발자의 동시성 제어에 대한 이해도가 중요하다. 응답 시간 - 멀티 스레드는 컨텍스트 스위칭이 빠르기 때문에, 더 빠른 응답 시간을 요구하는 경우 유리할 수 있다. 플랫폼 및 언어 지원 - 사용 중인 프로그래밍 언어나 플랫폼이 멀티스레드 또는 멀티프로세스 중 어느 쪽을 더 잘 지원하는지도 중요한 요소가 될 수 있다. 2. 데드락을 해결하기 위한 전략을 두 가지 이상 설명하십시오.
1. 데드락 예방
(Deadlock Prevention)- 이 접근법은 데드락 발생을 원천적으로 차단한다.
- 데드락이 발생하는 네가지 필수 조건(상호 배제, 점유와 대기, 비선점, 순환 대기) 중 적어도 하나를 제거함으로써 데드락을 방지한다.
- 예를 들어, 비선점 조건을 제거하면 어떤 리소스도 필요할 때 다른 프로세스에 의해 선점될 수 있으며, 이는 데드락도 방지할 수 있다.2. 데드락 회피
(Deadlock Avoidance)- 데드락 회피는 시스템이 데드락 상태로 진입하는 것을 회피하는 전략이다.
- 이를 위해 시스템은 리소스 할당 결정 시 데드락의 가능성을 고려한다.
- 가장 유명한 예는 뱅커스 알고리즘(Banker's Algorithm)으로, 이는 프로세스에 리소스를 할당하기 전에 안전 상태를 유지할 수 있는지 확인한다.
- 만약 할당으로 인해 데드락이 발생할 위험이 있다면, 리소스는 할당되지 않는다.3. 데드락 탐지 및 회복
(Deadlock Detection
and Recovery)- 이 전략은 시스템이 데드락을 탐지하고, 이를 해결하기 위한 조치를 취하는 것을 포함한다.
- 데드락 탐지는 주기적으로 리소스 할당 그래프를 검사하여 순환 대기 조건을 찾는 것으로 이루어질 수 있다.
- 데드락이 탐지되면, 시스템은 프로세스를 중지하거나 리소스 할당을 롤백하여 데드락을 해결한다.4. 자원의 상호 배제 제거
(Ignoring Mutual
Exclusion)- 일부 경우에, 리소스의 상호 배제 조건을 제거할 수 있다.
- 예를 들어, 리소스가 복사가 가능하거나 공유가 가능한 경우, 여러 프로세스가 동시에 해당 리소스를 사용할 수 있다.
- 이러한 방식으로 상호 배제 조건을 제거함으로써 데드락 발생 가능성을 줄일 수 있다.3. Semaphore와 Mutex의 특징과 주요 차이점은 무엇인가요?
Semaphore - Semaphore는 공유 자원에 대한 접근을 제한하는 데 사용되며, 이는 특정 숫자로 초기화된다.
- 이 숫자는 동시에 해당 자원에 접근할 수 있는 스레드의 최대 수를 나타낸다.
- Semaphore는 스레드가 자원을 사용할 때마다 감소하고, 자원을 해제할 때마다 증가한다.Mutex - Mutex는 공유 자원에 대한 접근을 단일 스레드에게만 허용한다.
- 이는 주로 데이터의 무결성을 보호하기 위해 사용되며, 한 번에 하나의 스레드만이 공유 자원에 접근할 수 있도록 한다.
- Mutex는 소유권 개념을 가지고 있어, 잠금을 건 스레드만이 잠금을 해제할 수 있다.정리 - 이 두 가지 매커니즘은 모두 동시성을 관리하고 데이터 무결성을 보장하는 데 필수적이지만, 사용되는 상황과 목적에 따라 선택된다.
- Mutex는 보다 엄격한 제어가 필요할 때, Semaphore는 여러 자원에 대한 동시 접근을 허용할 때, 특히 Counting Semaphore는 자원의 수량이 제한되어 있을 때 유용하다.'정글 크래프톤 5기 회고 및 정리 > WIL' 카테고리의 다른 글
[WEEK11] 정글 5기 - 정글 끝까지(PintOS) - Virtual Memory (0) 2024.05.30 [WEEK09] 정글 5기 - 정글 끝까지(PintOS) - User Programs (0) 2024.05.16 [WEEK07] 정글 5기 - 캐시(발표를 위한 정리) (0) 2024.05.09 [WEEK07] 정글5기 - 탐험 준비 - 웹서버 만들기 (0) 2024.05.02 [WEEK06] 정글5기 - 탐험준비 - Malloc Lab (0) 2024.04.25