MLFQ 시뮬레이터를 C언어로 구현하기
아래 코드가 베이스코드이다.
#include <stdio.h>
#include <stdlib.h>
// Structure to represent a process
typedef struct Process {
int pid;
int arrival_time;
int burst_time;
int remaining_burst_time;
int completion_time;
int turnaround_time;
int waiting_time;
int queue_level;
struct Process* next;
} Process;
// Structure to represent a queue
typedef struct Queue {
Process *head, *tail;
int time_quantum;
} Queue;
// Function to create a new process
Process* createProcess(int pid, int arrival, int burst) {
Process* p = (Process*)malloc(sizeof(Process)); // 메모리를 할당하여 새로운 프로세스 구조체를 생성
p->pid = pid; // 새로운 프로세스의 pid를 입력한 pid로 설정
p->arrival_time = arrival; // 새로운 프로세스의 arrival_time을 입력한 arrival로 설정
p->burst_time = burst; // 새로운 프로세스의 burst_time을 입력한 burst로 설정
p->remaining_burst_time = burst; // 초기 remaining_burst_time은 burst_time과 동일하게 설정
p->completion_time = 0;
p->turnaround_time = 0;
p->waiting_time = 0;
p->queue_level = 1; // Start in the highest priority queue
p->next = NULL;
return p;
}
// Function to create a new queue
Queue* createQueue(int quantum) {
Queue* q = (Queue*)malloc(sizeof(Queue));
q->head = q->tail = NULL; // 생성한 큐의 head와 tail을 NULL로 초기화
q->time_quantum = quantum; // 큐의 time_quantum(타임 슬라이스)을 입력한 quantum(타임 슬라이스)으로 설정
return q;
}
// Function to add a process to a queue
void enqueue(Queue* q, Process* p) {
if (q->tail == NULL) {
q->head = q->tail = p;
return;
}
q->tail->next = p;
q->tail = p;
p->next = NULL; // Ensure the new tail points to NULL
}
// Function to remove a process from the front of a queue
Process* dequeue(Queue* q) {
if (q->head == NULL) return NULL;
Process* p = q->head;
q->head = q->head->next;
if (q->head == NULL) q->tail = NULL;
p->next = NULL;
return p;
}
// Main MLFQ simulation function
void mlfq_scheduling(Process* processes[], int n) {
// Define the three queues with their time quanta
Queue* q1 = createQueue(4);
Queue* q2 = createQueue(8);
Queue* q3 = createQueue(-1); // FCFS (no specific quantum, runs until completion or preemption)
int current_time = 0;
int completed_processes = 0;
int i;
// Initially add all processes to the highest priority queue (Q1) at their arrival time
for (i = 0; i < n; i++) {
enqueue(q1, processes[i]);
}
while (completed_processes < n) {
Process* current_process = NULL;
Queue* current_queue = NULL;
// Find the highest priority non-empty queue
if (q1->head != NULL) {
current_queue = q1;
} else if (q2->head != NULL) {
current_queue = q2;
} else if (q3->head != NULL) {
current_queue = q3;
} else {
// No ready process, increment time
current_time++;
continue;
}
current_process = dequeue(current_queue);
// Determine the execution time
int exec_time;
if (current_queue->time_quantum == -1) {
// FCFS queue, run until completion
exec_time = current_process->remaining_burst_time;
} else {
// Round Robin queue, run for min of quantum or remaining time
exec_time = (current_process->remaining_burst_time < current_queue->time_quantum) ?
current_process->remaining_burst_time : current_queue->time_quantum;
}
// Simulate execution
current_process->remaining_burst_time -= exec_time;
current_time += exec_time;
// Check if process completed
if (current_process->remaining_burst_time == 0) {
current_process->completion_time = current_time;
current_process->turnaround_time = current_process->completion_time - current_process->arrival_time;
current_process->waiting_time = current_process->turnaround_time - current_process->burst_time;
completed_processes++;
free(current_process); // *출력이 나오기도 전에 메모리 해제하면 안됨..
} else {
// Process not completed, demote to the next queue
if (current_queue == q1) {
current_process->queue_level = 2;
enqueue(q2, current_process);
} else if (current_queue == q2) {
current_process->queue_level = 3;
enqueue(q3, current_process);
} else {
// Stays in Q3 (FCFS)
enqueue(q3, current_process);
}
}
}
// Print results (this basic simulation prints results as processes finish)
// A better approach would store completed processes in an array for structured output.
printf("All processes completed.\n");
}
int main() {
// Example processes: PID, Arrival Time, Burst Time
Process* processes[] = {
createProcess(1, 0, 10),
createProcess(2, 1, 5),
createProcess(3, 2, 8)
};
int n = sizeof(processes) / sizeof(processes[0]);
mlfq_scheduling(processes, n);
// Note: A real implementation for comprehensive results (Avg Turnaround/Waiting Time)
// needs a list of completed processes for final calculation.
return 0;
}
베이스코드를 기반으로 다음과 같은 특성을 고려해보자
MLFQ는 3개의 큐를 가지며(q1, q2, and q3), 각 큐는 FIFO로 동작함
q1, q2의 time slice(quantum)은 10, q3 의 time slice(quantum)은 20 으로 설정됨
q2, q3의 boost time 은 50 으로 설정됨
time의 최소 단위는 1로 설정됨
Process 의 수는 최대 100개이며, 파일로부터 프로세스의 정보를 load함
I/O 동작이 있는 경우, 자발적으로 CPU을 양보함
모든 프로세스가 종료되면 각 프로세스의 PID, turnaround time, response time을 각각 출력하고 최종 종료시간을 출력한 후 프로그램을 종료함.
첫 번째 칼럼은 PID, 그리고 순서대로 arrival time, run time, I/O 시작 시간, I/O runtime을 의미한다.
ex: 첫 번째 줄의 의미는 1번프로세스가 0초에 도착하여 30초 동안 수행하며 I/O 동작은 없음 (다섯 번째 칼럼이 0)
1 0 30 0 0
3 1 45 5 10
2 1 20 0 0
위 내용을 기반으로 코드에 추가할 로직:
- response time 추가
- I/O 시작 시간, 수행 시간, 완료여부, I/O 완료하고 다시 CPU를 사용할 수 있게 되는 시간 관련 변수들
- Boost time 추가 (boost time 마다 모든 프로세스 Q1으로 부스트
- 도착 시간 상관없이 Q1에 넣던 로직 제거 후, 현재 시간이 각 프로세스 도착 시간이 되었을 때 Q1에 추가하는 로직 추가
- 1초 단위 시뮬레이션으로 변경 (time unit = 1)
exec_time을 한 번에 계산하지 말고, 1초씩 프로세스를 실행하며 매 초마다 다음을 체크.
- 새 프로세스가 도착했는가?
- 현재 실행 중인 프로세스가 I/O를 시작할 시점인가?
- 타임 퀀텀(time slice)를 다 썼는가?
- 부스트 타임 (50)에 도달했는가?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
// Structure to represent a process
typedef struct Process {
int pid;
int arrival_time;
int burst_time;
int remaining_burst_time;
int first_run_time; // *프로세스가 처음으로 CPU를 할당받은 시간 (response time 계산에 사용)
int response_time; // *프로세스의 응답 시간 (first_run_time - arrival_time)
int io_start_time; // *프로세스가 I/O를 시작하는 시간 (0이면 I/O 없음)
int io_runtime; // *프로세스가 I/O를 수행하는 시간 (0이면 I/O 없음)
int io_done; // *프로세스가 I/O를 완료했는지 여부 (0: 미완료, 1: 완료)
int io_ready_time; // *프로세스가 I/O를 완료하고 다시 CPU를 사용할 수 있게 되는 시간
int completion_time;
int turnaround_time;
int waiting_time;
int queue_level;
struct Process* next;
} Process;
// Structure to represent a queue
typedef struct Queue {
Process* head, * tail;
int time_quantum;
} Queue;
// Function to create a new process
Process* createProcess(int pid, int arrival, int burst, int iostart, int iorun) {
Process* p = (Process*)malloc(sizeof(Process)); // 메모리를 할당하여 새로운 프로세스 구조체를 생성
p->pid = pid; // 새로운 프로세스의 pid를 입력한 pid로 설정
p->arrival_time = arrival; // 새로운 프로세스의 arrival_time을 입력한 arrival로 설정
p->burst_time = burst; // 새로운 프로세스의 burst_time을 입력한 burst로 설정(run time의미)
p->remaining_burst_time = burst; // 초기 remaining_burst_time은 burst_time과 동일하게 설정
p->io_start_time = iostart; // *새로운 프로세스의 io_starttime을 입력한 iostart로 설정
p->io_runtime = iorun; // *새로운 프로세스의 io_runtime을 입력한 iorun로 설정
p->io_done = (iorun == 0) ? 1 : 0; // *io_runtime이 0이면 I/O가 없으므로 io_done을 1로 설정하여 I/O가 완료된 것으로 간주, 그렇지 않으면 io_done을 0으로 설정하여 I/O가 아직 완료되지 않은 것으로 간주
p->io_ready_time = -1; // *io_ready_time을 -1로 초기화하여 프로세스가 처음에는 I/O를 수행하지 않았다고 가정
p->completion_time = 0;
p->turnaround_time = 0;
p->waiting_time = 0;
p->queue_level = 1; // 우선순위 큐에서 시작하므로 queue_level을 1로 설정
p->next = NULL;
return p;
}
// Function to create a new queue
Queue* createQueue(int quantum) {
Queue* q = (Queue*)malloc(sizeof(Queue));
q->head = q->tail = NULL; // 생성한 큐의 head와 tail을 NULL로 초기화
q->time_quantum = quantum; // 큐의 time_quantum(타임 슬라이스)을 입력한 quantum(타임 슬라이스)으로 설정
return q;
}
// Function to add a process to a queue
void enqueue(Queue* q, Process* p) {
if (q->tail == NULL) { // 큐가 비어있는 경우 head와 tail을 모두 새로운 프로세스로 설정
q->head = q->tail = p;
return;
}
q->tail->next = p; // 현재 tail의 next를 새로운 프로세스로 설정하여 들어온 프로세스를 큐의 다음으로 연결
q->tail = p; // 들어온 새로운 프로세스는 이제 큐의 tail이 됩니다
p->next = NULL; // 새로운 프로세스의 next는 NULL로 설정하여 큐의 끝을 나타냅니다
}
// Function to remove a process from the front of a queue
Process* dequeue(Queue* q) {
if (q->head == NULL) return NULL; // 큐가 비어있는 경우 NULL을 반환
Process* p = q->head; // 큐의 head를 p에 저장하여 반환할 프로세스를 지정
q->head = q->head->next;// 큐 head 다음 프로세스가 새로운 head가 됩니다
if (q->head == NULL) q->tail = NULL; // 큐에 한 개의 프로세스만 있었던 경우, head가 NULL이 되면 tail도 NULL로 설정하여 큐가 비어있음을 나타냅니다
p->next = NULL; // head였던 프로세스의 next를 NULL로 설정하여 큐에서 분리
return p;
}
// Main MLFQ simulation function
void mlfq_scheduling(Process* processes[], int n) {
// Define the three queues with their time quanta
Queue* q1 = createQueue(10);
Queue* q2 = createQueue(10);
Queue* q3 = createQueue(20); // FCFS (no specific quantum, runs until completion or preemption)
int current_time = 0;
int completed_processes = 0;
int time_slice_used = 0; // *현재 프로세스가 현재 큐에서 사용한 시간
Process* current_process = NULL;
int boost_time = 50; //*Q1으로 프로세스가 다시 올라오는 시간 간격 (예: 50ms마다 모든 프로세스가 Q1으로 부스트됨)
int i;
/*
for (i = 0; i < n; i++) {
enqueue(q1, processes[i]);
}
*/ //* 기존에 도착 시간 상관없이 q1에 넣던 로직 제거
while (completed_processes < n) { // 모든 프로세스가 완료될 때까지 반복
// * 신규 프로세스 도착 및 I/O 완료 체크: 현재 시간에 도착한 프로세스들과 I/O가 완료되어 CPU로 돌아올 준비가 된 프로세스들을 Q1에 추가하는 로직
for (i = 0; i < n; i++) { // * 도착 시간 로직 수정! 현재 시간에 도착한 프로세스들을 Q1에 추가
if (processes[i]->arrival_time == current_time) {
enqueue(q1, processes[i]);
}
else if (processes[i]->io_done == 0 && processes[i]->io_ready_time == current_time) { // * I/O가 완료되어 CPU로 돌아올 준비가 된 프로세스들을 Q1에 추가
processes[i]->io_done = 1; // * I/O가 완료된 것으로 표시
enqueue(q1, processes[i]); // * 프로세스를 Q1에 추가하여 CPU 스케줄링 대기
}
}
// *Priority Boost 체크: boost_time마다 모든 프로세스를 Q1으로 부스트하는 로직은 아래에서 처리
if (current_time > 0 && current_time % boost_time == 0) {
Process* temp;
// *현재 실행 중인 프로세스가 있다면 일단 큐로 돌려보내고 부스트(선점형 구조)
if (current_process != NULL) {
enqueue(q1, current_process);
current_process = NULL;
}
while ((temp = dequeue(q2)) != NULL) { temp->queue_level = 1; enqueue(q1, temp); }
while ((temp = dequeue(q3)) != NULL) { temp->queue_level = 1; enqueue(q1, temp); }
time_slice_used = 0;
}
// * 3. 실행할 프로세스 선택 (현재 실행 중인 게 없다면 우선순위 높은 큐부터 선택)
if (current_process == NULL) {
if (q1->head != NULL) { current_process = dequeue(q1); }
else if (q2->head != NULL) { current_process = dequeue(q2); }
else if (q3->head != NULL) { current_process = dequeue(q3); }
if (current_process != NULL) {
time_slice_used = 0;
// * Response Time을 위한 최초 실행 시간 기록
if (current_process->first_run_time == -1)
current_process->first_run_time = current_time;
}
}
// * 4. 1초간 실행 (Tick 발생)
if (current_process != NULL) {
current_process->remaining_burst_time--;
time_slice_used++;
current_time++;
// * 5. 자발적 CPU 양보 체크 (I/O 시작 시점 도달)
int cpu_used = current_process->burst_time - current_process->remaining_burst_time;
if (current_process->io_done == 0 && cpu_used == current_process->io_start_time) {
current_process->io_ready_time = current_time + current_process->io_runtime;
current_process = NULL; // * 큐에 넣지 않고 Blocked 상태로 전환
continue;
}
// * 6. 프로세스 종료 체크
if (current_process->remaining_burst_time == 0) {
current_process->completion_time = current_time;
current_process->turnaround_time = current_process->completion_time - current_process->arrival_time;
current_process->response_time = current_process->first_run_time - current_process->arrival_time;
completed_processes++;
current_process = NULL;
}
// * 7. 타임 퀀텀 소진 체크 (강등 로직)
else if (time_slice_used == (current_process->queue_level == 3 ? 20 : 10)) {
if (current_process->queue_level == 1) {
current_process->queue_level = 2;
enqueue(q2, current_process);
}
else {
current_process->queue_level = 3;
enqueue(q3, current_process);
}
current_process = NULL;
}
}
else {
current_time++; // * 실행할 프로세스가 없어도 시간은 흐름 (Idle)
}
}
printf("All processes completed. Final Time: %d\n", current_time);
for (i = 0; i < n; i++) {
printf("PID: %d, Turnaround: %d, Response: %d\n",
processes[i]->pid, processes[i]->turnaround_time, processes[i]->response_time);
free(processes[i]);
}
}
int main() {
// Example processes: PID, Arrival Time, Burst Time, I/O start, I/O runtime
FILE *fp = fopen("trace1.txt", "r");
if (fp == NULL) {
perror("Unable to open file!");
return 1;
}
Process* processes[100]; // 프로세스 최대 100개
int n = 0;
int pid, arrival, burst, iostart, iorun;
while (fscanf(fp, "%d %d %d %d %d", &pid, &arrival, &burst, &iostart, &iorun) != EOF) { //
processes[n] = createProcess(pid, arrival, burst, iostart, iorun); // 파일에서 읽은 프로세스 정보를 사용하여 새로운 프로세스를 생성하고 processes 배열에 저장
processes[n]->io_done = (iorun == 0) ? 1 : 0; // *io_runtime이 0이면 I/O가 없으므로 io_done을 1로 설정하여 I/O가 완료된 것으로 간주, 그렇지 않으면 io_done을 0으로 설정하여 I/O가 아직 완료되지 않은 것으로 간주
processes[n]->first_run_time = -1; // *프로세스가 아직 CPU를 할당받지 않았으므로 first_run_time을 -1로 초기화
n++; // *프로세스 개수 증가
}
fclose(fp);
mlfq_scheduling(processes, n);
return 0;
}
제공된 베이스 코드는 타임 퀀텀만큼 실행 시간을 한 번에 차감하는(Chunky) 구조였습니다. 하지만 본 과제에서는 "time의 최소 단위는 1로 설정됨" 조건과 프로세스가 "I/O 동작이 있는 경우, 자발적으로 CPU를 양보함" 이라는 조건이 주어졌습니다.
이를 정확히 시뮬레이션하기 위해, 프로세스의 실행 시간을 한꺼번에 계산하지 않고 시스템의 메인 루프를 ‘1초 단위’로 동작하도록 전면 개편했습니다. 이를 통해 매 초마다 프로세스의 도착, I/O 시작 및 종료, 그리고 50초 주기의 Priority Boost가 정확한 시점에 발생하도록 설계하였습니다.
- 구조체 확장 및 변수 추가

베이스 코드의 Process 구조체에는 I/O를 처리할 변수가 없었습니다. 따라서 I/O 동작 관리를 위한 변수들과, 과제에서 요구한 response time을 계산하기 위한 변수를 구조체에 추가했습니다.
- 실시간 프로세스 도착 및 I/O 복귀 처리(MLFQ 함수 내부에서)

기존에 도착 시간 상관없이 Q1에 삽입하던 로직을 제거하고, 1) 현재 시간에 도착한 신규 프로세스 2) I/O 수행을 마치고 복귀하는 프로세스를 식별해서 Q1에 삽입하도록 수정했습니다.
- 기아 현상(Starvation) 방지를 위한 Priority Boost (MLFQ 함수 내부)

과제에 따라 boost_time 변수를 50으로 선언해서 기아 현상 방지를 위한 priority boost 로직을 구성했습니다. 현재 CPU를 점유 중인 프로세스가 있다면 이를 선점하여 큐로 강제 반환시킨 후, 하위 큐(Q2, Q3)의 모든 프로세스를 Q1으로 이동시켰습니다.
- 1초 단위 실행 및 자발적 I/O 양보

뭉텅이로 타임 퀀텀만큼 실행 시간 한 번에 차감하는 구조에서 ‘time의 최소 단위는 1로 설정됨’ 이라는 조건에 맞게 로직을 수정했습니다. 그리고 cpu 사용한 시간을 기록하는 변수와 I/O 실행여부, I/O 시작시간을 이용해 자발적 CPU 양보하는 로직으로 개선하였습니다.
- 응답 시간, 반환 시간 계산 및 프로세스 종료 여부 확인 (MLFQ 함수 내부)

현재 프로세스의 남은 실행 시간이 0인지 확인하고 응답 시간, 반환 시간 등을 계산하고 완료된 프로세스 개수를 센 뒤 CPU를 내려놓는 로직으로 개선하였습니다.
- 타임 퀀텀(slice) 소진에 따른 우선순위 큐 강등 로직 (MLFQ 함수 내부)

타임 퀀텀(타임 슬라이스) 소진 후 프로세스의 우선순위 큐가 강등되는 로직을 개선하였습니다. 그리고 MLFQ 함수에서 모든 프로세스가 끝날 때까지 반복하는 while문 끝에 current_time++; 코드를 통해 실행할 프로세스가 없어도 시간(1초)가 흐르도록 하였습니다.
- 출력문 (MLFQ 함수 내부, while 문 외부)

모든 프로세스가 종료되고 출력되는 출력문입니다. 종료시점 시간을 출력하고 각 프로세스의 반환시간, 응답시간을 출력하고 메모리를 해제하도록 반복문을 구성해서 모든 프로세스가 메모리 낭비를 일으키지 않게끔 구성하였습니다.
- MLFQ.c 파일의 main 함수

과제에서 주어진 trace1.txt 파일을 읽어서 순서대로 매개변수로 동작하게끔 구성하였습니다. 데이터가 없을 때까지 프로세스를 만들고 MLFQ 스케줄링을 진행하도록 하였습니다.
- Trace1.txt 내용
1 0 30 0 0
3 1 45 5 10
2 1 20 0 0
4 3 10 5 5
5 0 15 0 0
7 1 60 10 20
8 2 40 0 0
6 1 15 5 10
9 4 30 0 0
10 1 100 10 20
- *최종 출력 화면

① 초기 스케줄링과 응답 시간(Response Time)의 변화
- 결과 수치: PID 1의 응답 시간은 0인 반면, PID 4는 67, PID 9는 71 등으로 다양하게 나타났습니다.
- 동작 원리: PID 1은 0초에 도착하여 즉시 CPU를 할당받았기 때문에 응답 시간이 0입니다. 반면, 1초에 동시다발적으로 도착한 나머지 프로세스들은 가장 높은 우선순위인 Q1에 삽입되었으나, 단일 CPU 환경이므로 앞선 프로세스들이 타임 슬라이스(10 단위)를 소모하거나 I/O를 수행할 때까지 Ready Queue에서 대기해야 했습니다. 이로 인해 도착 순서 및 큐 대기 시간에 따라 응답 시간의 편차가 발생한 것입니다.
② 타임 퀀텀 소진에 따른 강등(Demotion) 및 종료 순서 혼재
- 결과 수치: 출력된 순서가 PID 순서와 일치하지 않으며, Turnaround Time 역시 PID 5(105초), PID 2(114초) 등 비교적 짧은 작업들이 먼저 종료되었습니다.
- 동작 원리: 본 시뮬레이터는 프로세스가 완전히 종료될 때(remaining_burst_time == 0) 결과를 출력하도록 설계되었습니다. 실행 시간(Burst Time)이 짧거나 I/O 비중이 높아 CPU를 자발적으로 양보한 프로세스들은 높은 우선순위 큐(Q1, Q2)에 머물며 빠르게 작업을 마쳤습니다. 반면, CPU 연산 위주의 긴 프로세스들은 퀀텀을 소진하고 하위 큐(Q3)로 강등되어 실행 빈도가 낮아졌기 때문에 늦게 종료되었습니다.
③ 프로세스 도착 시간(Arrival Time)의 정밀한 연산 검증
- 결과 수치: 마지막으로 종료된 PID 10의 Turnaround Time은 364이며, 전체 시뮬레이션 종료 시간인 Final Time은 365입니다.
- 동작 원리: 반환 시간 공식($Turnaround Time = Completion Time - Arrival Time$)에 따라, 종료 시간 365초에서 Turnaround Time 364초를 역산하면 해당 프로세스의 실제 도착 시간이 1초임을 알 수 있습니다. 이는 1초 단위(Tick)로 시뮬레이터를 동작시키며 현재 시간과 프로세스의 도착 시간을 매 순간 정확히 비교하여 큐에 삽입한 로직이 오차 없이 수행되었음을 나타냅니다.
④ Priority Boost를 통한 기아 현상(Starvation) 방지
- 결과 수치: Turnaround Time이 200~300초대인 무거운 프로세스들(PID 7, 8, 10 등)도 영원히 대기하지 않고 최종 365초 안에 모두 작업을 마쳤습니다.
- 동작 원리: 이들은 대부분의 시간을 최하위 우선순위인 Q3에서 보냈지만, 시뮬레이터에 구현된 current_time % boost_time == 0 조건에 따라 매 50초마다 발생하는 Priority Boost를 통해 정기적으로 Q1으로 격상되었습니다. 시스템이 365초 동안 동작하며 총 7번의 부스트(50, 100... 350)를 발생시켰고, 이 덕분에 CPU 위주의 무거운 작업들도 기아 현상 없이 스케줄링을 완료할 수 있었습니다.
+ c언어 복습하기
## 1. -> 기호: "주소를 따라가서 문을 열어라"
->는 멤버 변수에 접근하는 기호가 맞습니다. 다만, **'포인터 변수'**를 통해서 접근할 때만 사용하는 특별한 화살표예요.
- . (점 연산자): 구조체 변수 실체에서 멤버를 찾을 때 씁니다. (예: Process p; p.pid;)
- -> (화살표 연산자): 구조체의 **주소(포인터)**만 알고 있을 때, 그 주소로 찾아가서 멤버를 찾을 때 씁니다.
컴퓨터 내부의 속마음: tail->next는 사실 (*tail).next와 똑같은 의미입니다. "포인터 tail이 가리키는 곳으로 가서(*), 그 집의 next라는 방을 열어라"라는 뜻
만약 포인터(*)와 화살표(->)를 쓰지 않고 배열을 쓴다면, 프로세스가 우선순위 큐 사이를 이동할 때마다 그 무거운 구조체 데이터 전체를 메모리의 이 방에서 저 방으로 계속 이사시켜야 합니다.
하지만 Process *tail 처럼 포인터를 쓰면:
- 실제 데이터는 메모리 한곳에 가만히 둡니다.
- 우리는 아주 가벼운 **'주소값(포인터)'**만 주고받으며 화살표(->)로 연결만 해주면 됩니다.
- 이게 바로 운영체제가 수천 개의 프로세스를 아주 빠르게 관리하는 비결입니다.
'CS > OS' 카테고리의 다른 글
| 운영체제(OS)-WEEK5 (2) [페이징(Paging)]+WEEK6 (1) (0) | 2026.04.03 |
|---|---|
| 운영체제(OS)-WEEK4 [메모리 가상화(Memory Virtualization)] (0) | 2026.04.01 |
| 운영체제(OS)-WEEK3(1) 스케줄링(Scheduling) (0) | 2026.03.17 |
| 운영체제(OS)-week2 (0) | 2026.03.17 |
| 운영체제(OS)-가상화 (week1) (0) | 2026.03.14 |