[CS] 3. OS

이재호·2025년 2월 25일

cs

목록 보기
3/3

문제 출처: https://docs.google.com/document/d/1ebOe9TvEFWVpae8cszHVoptYxwn8QACE/edit?tab=t.0

Kernel

  • Kernel을 필요에 의해 어느정도 수정했다고 하자. 이 kernel이 제대로 작동하는지를 알기 위해서 어떤 test를 해야 하나?

수정한 커널을 컴파일하고 설치한 후, 시스템이 정상적으로 부팅되는지 확인하는 부팅 테스트를 진행하고, dmesg 명령어를 통해 부팅 과정에서 발생한 커널 로그를 확인한다. 만약 커널 내부의 특정 기능만 수정되었다면, kselftest와 같은 명령어를 통해 유닛테스트를 진행한다. 또한, 모듈 및 드라이버 테스트, 스트레스 테스트, 회귀 테스트, 보안 테스트 등을 진행해야 한다.

  • Interrupt란 무엇인가? interrupt를 두 종류로 나눈다면 어떻게 되는가? (software interrupt/hardware interrupt) 두 interrupt의 차이는 무엇인가? 두 interrupt의 handler 를 서로 구분해서 구현해야 하는 것이 좋은가, 아니어도 상관 없는가?

Interrupt란 CPU가 실행 중인 작업을 잠시 멈추고 더 중요한 작업(예: 입출력, 예외 처리)을 처리한 후 다시 원래 작업으로 돌아가는 메커니즘이다. interrupt에는 두 종류가 있는데 먼저, software interrupt는 프로그램이 의도적으로 명령어를 통해 발생시키는 interrupt다. 보통 Systeml Call이나 Exception 상황에서 발생한다. 반면에 hardware interrupt는 외부 하드웨어 장치(예: 키보드, 마우스)가 CPU에 신호를 보내어 발생하는 interrupt다. 보통 장치의 입력시 발생하며, 이때 Interrupt Controller를 통해 CPU가 interrupt를 수신한다. 두 interrupt는 성질이 달라 서로 구분해서 구현해야 한다. 예를 들어, 소프트웨어 interrupt는 프로세스의 요청으로 발생하고 하드웨어 interrupt는 외부 장치로부터 발생한다. 따라서 이를 각각 처리하는 handler가 필요하며, 전자의 경우 System Call Handler에 의해, 그리고 후자의 경우 Interrupt Controller에 의해 처리가 된다. 또한, 보통 하드웨어 interrupt가 우선순위가 더 높기에 이를 구분할 필요도 있다.

  • 시스템 콜과 인터럽트의 차이는? 인터럽트가 걸리면 어떤 일이 일어나고 처리 후에 어떻게 이전 상태로 돌아가는가?

시스템 콜은 프로세스가 커널의 기능을 이용하기 위해 의도적으로 호출하지만, 인터럽트는 의도와 관계없이 예상치 못한 외부 상황이나 예와 처리 등에 의해서 발생된다. 인터럽트가 걸리면 먼저, 현재 실행 중이던 프로그램의 상태(레지스터, 프로그램 카운터 등)를 저장한다. 그러고 나서 다른 작업을 처리한 후, 저장했던 프로그램의 상태를 복원하여 이전 상태로 돌아간다.

Thread & Process

  • Thread와 process의 차이는 무엇인가?

thread는 프로세스 내에서 실행되는 가장 작은 실행 단위이며, process는 실행 프로그램을 의미한다. thread의 경우 같은 프로세스의 메모리 및 자원을 공유하지만, process는 각 프로세스마다 별도의 메모리를 갖는다는 차이가 있다.

  • IPC가 무엇인가?

IPC란 Inter Process Communication의 약자로, 프로세스 간 데이터를 주고 받는 기술을 의미한다. 왜냐하면 프로세스는 독립적인 메모리를 할당받기 때문에 프로세스 간 직접 데이터를 주고받을 수 없다. 따라서 IPC를 통해 데이터를 주고 받는다.

  • Thread끼리 context switching 하는 과정에 대해 설명하시오. 같은 프로세스 내부의 thread들끼리 전환되는 것과 다른 프로세스간의 thread 까리 전환되는 것이 어떻게 다른가?

thread 간의 context switching은 동일 프로세스 내 혹은 다른 프로세스 간의 방식으로 두 가지가 있다. 우선 같은 프로세스 내부에서의 context switching은 현재 실행 중이던 thread의 스택과 레지스터만 변경하여 전환이 가능하지만, 다른 프로세스 간의 thread context switching은 현재 프로세스를 다른 프로세스로 바꾸고 해당 프로세스의 thread로 변경하여야 하기 때문에 전자와 달리 스택 및 레지스터와 더불어 page 테이블도 변경해야 한다는 점이 다르다.

  • Non-preemptive scheduling이란?

Non-preemptive sceduling이란, CPU가 한 프로세스에 할당되면, 그 프로세스가 스스로 종료하거나 I/O에 의해 대기 상태로 전환되기 전까지 CPU를 계속 사용하는 방식의 스케쥴링 기법이다.

  • 요즘 많은 사람들이 각각 자신만의 스마트폰을 사용하고 있다. 이처럼 각 개인 스마트폰을 위하여 process system을 design하려고 한다. 스마트폰에서 각 application이 하나의 process로 독립해서 실행하는 것이 나을까? 아니면, 하나의 thread로 만들어져서 실행하는 것이 나을까? 어느 쪽이 나을지 결정하고, 그 이유를 설명하라.

각 앱을 하나의 프로세스로 독립해서 실행하는 것이 더 낫다. 왜냐하면 한 앱에서 크래시가 발생하더라도 다른 앱에 영향을 미치지 않아야 하고, OS는 프로세스 단위로 메모리 사용량을 제한하고 백그라운드 프로세스를 효율적으로 관리할 수 있기 때문이다. 또한 한 앱을 백그라운드에서 실행하면서 다른 앱을 실행하는 멀티테스킹 측면에서도 이점이 있다. 예를 들어, 음악 앱을 백그라운드에서 실행하면서 다른 앱을 실행하는 경우를 들 수 있다.

Concurrency

  • Sequential program과 multithread program에서 error detection에 대한 차이점에는 어떤 것이 있나?

우선 sequential program은 단일 thread에서 실행되므로 오류 탐지가 비교적 더 쉽고, 동일한 실행 흐름을 보장하기에 디버깅이 더 쉽다. 반면에 multihtread program은 실행 순서가 매번 달라질 수 있으며 이에 따라 오류가 재현되지 않아 오류 탐지가 어려울 수 있다. 즉, 동기화 문제로 디버깅이 더 어렵다. 따라서 multithread program은 오류 탐지를 위해 별도의 semaphore와 같은 별도의 동기화 도구가 필요하다.

  • Critical section이란?

여러 스레드나 프로세스가 동시에 접근할 수 있는 공유 자원에 대해, 한 번에 하나의 스레드만 접근 가능하도록 보장하는 특정 구간을 의미한다. 만약 동시 접근이 발생할 경우 race condition과 같은 문제가 발생할 수 있으며, 이를 방지하기 위해 semaphore와 같은 동기화 기법이 필요하다.

  • 세마포어의 개념은? 주요 연산 2가지는? 어떻게 구현해야 하는가?

공유 자원에 대한 접근을 제어하고 동기화를 관리하는 동기화 기법이다. 동시 접근의 경우 발생 가능한 race condition 문제 등을 방지하기 위해 필요하다. 주요 연산은 Wait과 Signal 연산이다. 세마포어에는 카운트 값이 존재하는데, 이 카운트가 0이면 해당 스레드 혹은 프로세스는 대기하여 대기 큐에 들어가게 되고, 0이 아니면 카운트 값을 1 감소시킨 후 자원을 할당한다. 이 과정이 Wait이다. 반면에 Signal은 다음과 같다. 카운트 값을 1 증가시킨 후 만약 대기 큐에 스레드 혹은 프로세스가 존재한다면 대기 중이던 스레드 혹은 프로세스를 깨운다. 코드로 설명하면 다음과 같이 간단히 구현할 수 있다.

def wait(semaphore_cnt):
	if semaphore_cnt == 0:
    	add_to_wait_queue()
    else:
    	semaphore_cnt -= 1
#
def signal(semaphore_cnt):
	semaphore_cnt += 1
    if is_not_empty_queue():
    	wake_up_wait()

Virtual Memory

  • Virtual Address와 Virtual memory에 대해 설명하시오.

가상 주소(Virtual Address)는 프로그램이 실행 중일 때 사용되는 논리적 주소로, 프로그램은 자신에게 할당된 가상 주소를 통해 메모리에 접근하게 되고, OS는 이 가상 주소를 실제 주소로 변환하여 처리한다. 가상 메모리(Virtual Memory)는 물리적 메모리가 부족할 때, 하드디스크와 같은 보조 기억 장치를 활용하여 프로그램이 사용할 수 있는 주소 공간을 확장하는 메커니즘이다. OS는 물리적 메모리의 한계를 넘는 메모리 공간을 제공할 수 있으며, 프로그램은 실제 물리적 메모리가 부족하더라도 마치 더 많은 메모리를 가진 것처럼 동작할 수 있다.

  • 어떤 C program으로 작성되어 수행중인 process가 있다고 가정하자. C언어에서는 직접적으로 주소를 변수에게 지정해 줄 수 있다. 만약 주소 1, 2, 3, 4에 변수를 잡아서 어떤 일을 수행하는 process라고 하자. 이 process를 한 시스템에 동시에 두번 수행 시켰다. 그랬을 때 한 프로세스가 1, 2, 3, 4 주소에 있는 변수를 바꿨을 때 다른 프로세스의 변수들에도 영향을 끼치는가?

기본적으로 각 프로세스는 독립된 가상 메모리 공간을 갖기 때문에, 1, 2, 3, 4 주소에 있는 변수를 바꿔도 서로 영향을 주지 않는다. 하지만, 만약 공유 메모리를 사용할 경우, 한 프로세스가 해당 메모리의 값을 변경하면 다른 프로세스에도 영향을 끼칠 것이다.

  • C로 숫자로 직접 입력된 주소를 참조하는 프로그램을 짜서 컴파일한 후, 두 개를 실행시켰다고 하자. 그러면 이 두 프로세스는 물리적으로 같은 곳을 참조하나? 만약 아니라면, 어떻게 서로 다른 물리적 공간을 참조할 수 있나?

현대 운영 체제에서 사용하는 가상 메모리 시스템은 각 프로세스에게 독립적인 주소 공간을 할당한다. 각 프로세스는 자신만의 가상 주소 공간을 가지게 되며, 운영 체제가 이를 물리적 주소로 변환해준다. 이렇게 하면 각 프로세스는 자신에게 할당된 메모리 공간을 사용한다고 생각하지만, 실제 메모리의 서로 다른 주소를 참조하게 된다.

  • Logical address와 physical address의 차이는 무엇인가?

논리 주소(logical address)는 프로그램이나 프로세스가 사용하는 주소로, 실제 메모리에서 사용되는 주소가 아니라 가상 시스템에서 사용되는 주소이며, 운영 체제에 의해 할당된다. 반면에 물리 주소(physical address)는 실제 메모리의 물리적인 위치를 가리키는 주소이며, 하드웨어가 사용하는 주소다. 실제 메모리에 저장된 데이터의 물리적인 위치를 나타낸다.

  • Logical address를 physical address로 바꾸어주는 hw가 무엇인가?

MMU(Memory Management Unit)

  • 프로세스는 가상 메모리 주소로 어떻게 실제 메모리 주소를 찾아가는가?

먼저, 가상 주소에서 페이지 번호와 페이지 오프셋을 추출한다. 그리고 MMU는 해당 페이지 번호를 활용해 페이지 테이블을 조회한 후, 페이지 테이블에서 물리적 페이지 번호를 찾는다. 그리고 물리적 페이지 번호에 페이지 오프셋을 더하여 실제 메모리 주소를 찾는다.

  • OS의 캐시 메모리의 사이즈를 구하기 위한 프로그램을 어떻게 구현하면 되는가?

캐시 메모리의 사이즈를 구하기 위한 프로그램을 구현하려면, 캐시의 히트율, 미스율, 접근 시간 등을 측정하는 방법을 활용하여 구현해야 한다.

Paging

  • Paging이 무엇인가? paging을 할 때 어떻게 실제 메모리 주소에 데이터를 전송하는가? page table에는 어떤 항목이 저장되는가? page table은 어디에 저장되는가? page table이 메모리에 저장되면, paging을 할 때 메모리를 두 번 참조해야 되는데, 좀 더 빠르게 하는 방법은 없는가? TLB에는 어떤 항목이 저장되는가?

페이징은 프로그램의 가상 주소 공간을 고정된 크기로 나눠, 이를 물리 메모리의 고정된 크기로 나눠진 블록에 대응시켜, 가상 메모리를 관리하는 기법이다.
보통 가상 주소 공간에 페이지 번호와 페이지 오프셋이 저장되는데, 페이지 번호를 통해 페이지 테이블에서 실제 메모리의 블록 주소를 찾은 후 여기에 페이지 오프셋을 더하여 실제 메모리 주소로 데이터를 전송할 수 있다.
페이지 테이블에는 블록 번호, 유효 비트, 수정 비트, 읽기/쓰기 비트, 접근 비트 등이 저장된다.
페이지 테이블은 물리적 메모리에 저장된다.
블록 번호를 찾을 때와 실제 메모리 주소를 찾을 때로 메모리를 두 번 참조하게 되는데 이를 빨리 하기 위해서 TLB(Translation Lookaside Buffer)가 사용된다. TLB는 페이지 테이블의 일부 정보를 캐시하여, 가상 주소에서 물리 주소로 변환되는 시간을 단축시킨다.
TLB에는 페이지 번호, 블록 번호, 유효 비트, 접근 비트 등이 저장된다.

  • Virtual memory에서 page replacement policy에는 어떤 것이 있는가? LRU의 단점은?

page replacement policy에는 FIFO(First-In First-Out), LRU(Least Recently Used), Clock, OPT, NRU(Not Recently Used), Second-Chance 등이 있다. LRU는 언제 페이지가 마지막으로 사용되었는지 추적해야 하므로 구현 비용이 높고 효율성이 떨어진다는 단점이 있다. 또한, 페이지 교체가 발생할 경우 비교적 많은 연산이 필요하기에 성능이 저하된다는 단점이 있다.

  • 운영 체제에서 memory management 기법중 하나로 paging이 많이 사용되고 있다. Paging 기법의 장⋅단점으로는 무엇이 있으며, hierarchical paging 혹은 inverted page table은 어떤 환경에서 유리한가?

페이징 기법을 통해 각 페이지가 물리 메모리의 어떤 위치에 배치되더라도 상관이 없어 외부 단편화를 방지할 수 있으며, 실제 메모리보다 더 큰 가상 메모리 공간을 사용할 수 있다는 장점이 있다. 또한, 각 페이지는 독립적으로 관리되어 메모리 보호 및 관리 측면에서 이점이 있으며, 페이지 크기가 일정하여 효율적인 메모리 사용이 가능하다는 장점이 있다.
반면에 페이지는 고정된 크기를 갖기에 각 페이지에 여유 공간이 생길 수 있어 내부 간편화 문제점이 있을 수 있으며, 페이지 테이블 관리 비용이 많이 든다는 단점이 존재한다. 또한 페이지 교체 시 큰 오버헤드가 발생할 수 있으며, TLB 미스가 발생할 경우 페이지 테이블을 참조하는 시간이 길어져 성능 저하 이슈가 있을 수 있다는 단점이 있다.
hierarchical paging은 페이지 테이블을 여러 라벨로 나누어 관리하는 방법으로, 큰 가상 공간 메모리 공간을 다루는 환경에서 유리하다. 반면에 inverted page table은 물리 메모리에 대해 하나의 엔트리만 유지하며 가상 주소를 물리 주소로 매핑하는 방법으로, 작은 가상 메모리 공간을 다루는 환경에서 유리하다.

profile
천천히, 그리고 꾸준히.

0개의 댓글