본문 바로가기
KraftonJungle2기/Today I Learned

[TIL] Pintos - 가상 메모리 관련 개념 공부2

by SooooooooS 2023. 6. 15.
728x90

1. 아침 문제 풀이

1. 10026번 - 적록색약

import sys
from collections import deque

N = int(sys.stdin.readline())
pic = [list(sys.stdin.readline().strip()) for _ in range(N)]

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def bfs(x, y) :
    queue = deque()
    queue.append((x, y))
    visited[x][y] = True

    while queue :
        cx, cy = queue.popleft()
        for i in range(4) :
            nx, ny = cx + dx[i], cy + dy[i]
            if nx >= 0 and nx < N and ny >= 0 and ny < N :
                if not visited[nx][ny] and pic[cx][cy] == pic[nx][ny] :
                    queue.append((nx, ny))
                    visited[nx][ny] = True         

def red_green(x, y) :
    queue = deque() 
    queue.append((x, y))
    rg_visited[x][y] = True

    while queue :
        cx, cy = queue.popleft()
        for i in range(4) :
            nx, ny = cx + dx[i], cy + dy[i]
            if nx >= 0 and nx < N and ny >= 0 and ny < N :
                if not rg_visited[nx][ny] :
                    if pic[cx][cy] == pic[nx][ny] or (pic[cx][cy] != 'B' and pic[nx][ny] != 'B') :
                        queue.append((nx, ny))
                        rg_visited[nx][ny] = True 

visited = [[False] * N for _ in range(N)]
rg_visited = [[False] * N for _ in range(N)]
count = 0
rg_count = 0
for i in range(N) :
    for j in range(N) :
        if not visited[i][j] :
            bfs(i, j)
            count += 1
        if not rg_visited[i][j] :
            red_green(i, j)
            rg_count += 1
print(count, rg_count)
저번에도 푼 문제로 그때와 거의 동일하게 풀었다.
그 당시보다는 적록색약 탐색시 간단하게 생각하여 구현했다.

다른 사람의 풀이를 보니 같은 탐색함수를 사용하되 적록색약 탐색전에 R, G를 합쳐준다.
1. 함수를 2개 구현
2. 이중 반복문을 한번 더 사용하여 탐색

위의 두가지를 고민해보는 문제였다.

2. 기본 코드 분석

1. page struct

//include/vm/vm.h
struct page {
  const struct page_operations *operations;
  void *va;              /* Address in terms of user space */
  struct frame *frame;   /* Back reference for frame */

  union {
    struct uninit_page uninit;
    struct anon_page anon;
    struct file_page file;
#ifdef EFILESYS
    struct page_cache page_cache;
#endif
  };
};

🗒️ Union

  공용체는 메모리 영역에 다른 유형의 데이터를 저장할 수 있는 특수 데이터 유형

  여러 구성원이 있지만 한 번에 하나의 구성원만 값을 포함

  ✅ 우리 시스템의 페이지가 uninit_page, anon_page, file_page 또는 page_cache가 될 수 있음을 의미


2. page_operations struct

//include/vm/vm.h
struct page_operations {
  bool (*swap_in) (struct page *, void *);
  bool (*swap_out) (struct page *);
  void (*destroy) (struct page *);
  enum vm_type type;
};

🗒️ 함수 포인터(Function pointer)

  함수의 시작 주소 또는 메모리 내의 실행 가능한 코드를 가리키는 포인터

void Func(int, int); //함수

void (*ptr_fun) (int, int) = Func; //함수 포인터

함수 포인터의 포인터 타입은 함수의 반환값매개변수에 의해 결정

→ 함수의 원형을 알아야만 해당 함수에 맞는 함수 포인터를 만들 수 있다.

 

🔗 http://www.tcpschool.com/cpp/cpp_function_pointer


① file일 경우 실행될 함수

// vm/file.c
static const struct page_operations file_ops = {
	.swap_in = file_backed_swap_in,
	.swap_out = file_backed_swap_out,
	.destroy = file_backed_destroy,
	.type = VM_FILE,
};

② 익명 페이지일 경우 실행될 함수

// vm/anon.c
static const struct page_operations anon_ops = {
	.swap_in = anon_swap_in,
	.swap_out = anon_swap_out,
	.destroy = anon_destroy,
	.type = VM_ANON,
};

③ 초기화 되지 않은 페이지일 경우 실행될 함수

// vm/uninit.c
static const struct page_operations uninit_ops = {
	.swap_in = uninit_initialize,
	.swap_out = NULL,
	.destroy = uninit_destroy,
	.type = VM_UNINIT,
};

✅ 함수 포인터를 사용하여 각 타입의 페이지에 알맞는 루틴이 수행된다.

#define destroy(page) if ((page)->operations->destroy) (page)->operations->destroy (page)

 

728x90