본문 바로가기
CS/OS

[OS] 07. 메모리 관리

by 원만사 2021. 12. 27.
반응형

1. 주소 바인딩

 프로그램이 메모리에 적재되면 그 프로세스를 위한 독자적인 주소 공간이 생성된다. 이를 논리적 주소(logical address) 혹은 가상 주소(virtual address)라고 부른다. 논리적 주소는 각 프로세스마다 독립적으로 할당되며 0번지부터 시작된다.

 반면 물리적 주소(physical address)는 물리적 메모리에 실제로 올라가는 위치를 말한다. 보통 물리적 메모리의 낮은 주소 영역에는 운영체제가 올라가고, 높은 주소 영역에는 사용자 프로세스들이 올라간다.

 

 프로세스가 실행되기 위해서는 해당 프로그램이 물리적 메모리에 올라가 있어야 한다. 또한 CPU가 기계어 명령 수행을 위해 논리적 주소를 통해 메모리 참조를 하게 되면 해당 논리적 주소가 물리적 메모리의 어느 위치에 매핑되는지 확인해야 한다. 이처럼 프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜주는 작업주소 바인딩(address binding)이라고 한다.

 

 주소 바인딩 방식은 프로그램이 적재되는 물리적 메모리의 주소가 결정되는 시기에 따라 세 가지로 분류할 수 있다.

 

① 컴파일 타임 바인딩 (compile time binding)

  • 컴파일을 하는 시점에 해당 프로그램이 물리적 메모리의 몇 번지에 위치할 것인지를 결정한다.
  • 프로그램이 절대주소로 적재되기 때문에 절대코드(absolute code)를 생성하는 바인딩 방식이라고도 한다.
  • 프로그램의 물리적 메모리의 위치를 변경하고 싶다면 컴파일을 다시 해야 한다.
  • 현대에는 잘 사용되지 않는다.

 

② 로드 타임 바인딩 (load time binding)

  • 프로그램의 실행이 시작될 때에 물리적 메모리 주소가 결정된다.
  • 로더(loader)의 책임하에 물리적 메모리 주소가 부여되며 프로그램이 종료될 때까지 물리적 메모리상의 위치가 고정된다.
  • 컴파일러가 재배치 가능 코드(relocatable code)를 생성한 경우에 가능한 주소 바인딩 방식이다.

※ 로더(loader) : 사용자 프로그램을 메모리에 적재시키는 프로그램

 

③ 실행시간 바인딩 (execution time binding / run time binding)

  • 프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경될 수 있는 바인딩 방식이다.
  • CPU가 주소를 참조할 때마다 주소 매핑 테이블(address mapping table)을 이용해 해당 데이터가 물리적 메모리의 어느 위치에 존재하는지 점검해야 한다.
  • 기준 레지스터(base register)와 한계 레지스터(limit register)를 포함해 MMU(Memory Management Unit: 메모리 관리 유닛)라는 하드웨어적인 지원이 있어야 한다.

※ MMU : 논리적 주소를 물리적 주소로 매핑해주는 하드웨어 장치

 

 

 이제 MMU를 사용해 가장 기본적인 주소 변환을 수행하는 MMU 기법에 대해서 알아보자. 여기에서는 프로그램의 주소 공간이 물리적 메모리의 한 장소에 연속적으로 적재되는 것으로 가정한다. 

 

MMU 기법에 의한 주소 변환

 CPU가 특정 프로세스의 논리적 주소를 참조하려고 할 때 MMU 기법은 그 주소값에 기준 레지스터(base register)의 값을 더해 물리적 주소값을 얻어낸다. 기준 레지스터는 해당 프로세스의 물리적 메모리 시작 주소를 가지고 있다. 즉, CPU가 요청하는 논리적 주소는 기준 레지스터에서 얼마나 떨어져 있는지를 나타내는 오프셋(offset) 개념이다. 

 

 MMU 기법에서는 문맥교환으로 CPU에서 수행 중인 프로세스가 바뀔 때마다 기준 레지스터의 값을 그 프로세스에 해당되는 값으로 재설정한다. 하지만 다중 프로그래밍 환경에서는 물리적 메모리 안에 여러 개의 프로세스가 동시에 올라가 있다. 이 때 CPU가 요청한 논리적 주소에 기준 레지스터를 더했을 때 해당 프로세스의 주소 공간을 벗어나는 경우가 있을 수 있다. 이를 방지하기 위해 운영체제는 한계 레지스터(limit regsiter)를 사용한다. 

 

 한계 레지스터는 자신의 주소 공간을 넘어서는 메모리 참조를 하려고 하는지 체크하는 용도로 사용되며, 해당 프로세스의 크기를 담고 있다. 메모리 보안을 달성하는 구체적인 방법은 다음과 같다.

기준 레지스터와 한계 레지스터에 의한 주소 변환

  1. CPU가 요청한 프로세스의 논리적 주소값이 한계 레지스터 내에 저장된 프로세스의 크기보다 작은지 확인한다.
  2. 작다면 논리적 주소값에 기준 레지스터값을 더해 물리적 주소를 구한 다음 해당 물리적 메모리 위치에 접근하도록 허락한다.
  3. 만약 논리적 주소값이 한계 레지스터의 값보다 크다면 트랩을 발생시켜 해당 프로세스를 강제종료시킨다.

 

2. 메모리 관리와 관련된 용어

1) 동적로딩 (dynamic loading)

  • 다중 프로그래밍 환경에서 메모리 사용의 효율성을 높이기 위해 사용하는 기법 중 하나
  • 프로세스 주소 공간 전체를 메모리에 다 올려놓는 것이 아니라, 프로세스 내에서 실행에 필요한 부분이 실제로 불릴 때마다 메모리에 적재한다.
  • 물리적 메모리에 더 많은 프로그램을 적재할 수 있기 때문에 메모리 이용의 효율성이 향상된다.
  • 운영체제의 특별한 지원 없이 프로그램 자체에서 구현이 가능하다.

 

2) 동적연결 (dynamic linking)

  • 연결이란, 목적 파일(object file)과 이미 컴파일된 라이브러리 파일(library file)들을 묶어 하나의 실행파일을 생성하는 과정이다.
  • 동적연결은 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결을 프로그램의 실행 시점까지 지연시키는 기법이다.
  • 실행 파일에 라이브러리 코드가 포함되지 않으며 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어진다.
  • 라이브러리 호출 시 스텁(stub)을 통해 해당 라이브러리가 메모리에 이미 존재하는지 살펴보고 그럴 경우 그 주소의 메모리 위치에서 직접 참조하며, 그렇지 않을 경우 디스크에서 동적 라이브러리 파일을 찾아 메모리로 적재한 후 수행한다.
  • 다수의 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한 번만 적재하므로 메모리 사용의 효율성을 높일 수 있다.
  • 운영체제의 지원을 필요로 한다.

※ 스텁(stub) : 실행파일의 라이브러리 호출 부분에 해당 라이브러리의 위치를 찾기 위한 작은 코드 

 

 

3) 중첩 (overlays)

  • 프로세스의 주소 공간을 분할해 실제 필요한 부분만을 메모리에 적재하는 기법
  • 프로그램의 크기가 물리적 메모리의 크기에 비해 작다면 주소 공간 전체를 한꺼번에 올릴 수 있지만 그렇지 않다면 분할해 메모리에 올리는 것
  • 단일 프로세스만을 메모리에 올려놓는 환경에서 사용되는 기법

 

4) 스와핑 (swapping)

  • 메모리에 올라온 프로세스의 주소 공간 전체를 디스크의 스왑 영역(swap area)에 일시적으로 내려놓는 것을 말한다.
  • 스왑 영역은 충분히 큰 저장공간이어야 하고 어느 정도의 접근 속도가 보장되어야 한다.
  • 프로세스가 종료되어 내쫓는 것이 아니라, 특정한 이유로 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것을 의미한다.
  • 스와핑의 가장 중요한 역할은 메모리에 존재하는 프로세스의 수를 조절하는 것이다.
  • 스와핑에서는 보통 디스크 내의 스왑 영역에 프로세스의 주소 공간이 순차적으로 저장되기 때문에, 스와핑에 소요되는 시간은 디스크 섹터에서 실제 데이터를 읽고 쓰는 전송시간(transfer time)이 대부분을 차지한다.

 

3. 물리적 메모리의 할당 방식

1) 연속할당 방식

프로세스를 메모리에 올릴 때 주소 공간을 여러 개로 분할하지 않고 물리적 메모리의 한 곳에 연속적으로 적재하는 방식

 물리적 메모리를 고정된 크기의 분할로 미리 나누어 놓는지 그렇지 않은지에 따라 고정분할 방식과 가변분할 방식으로 나뉜다.

 

고정분할 방식

  • 물리적 메모리를 주어진 개수만큼의 영구적인 분할(partition)로 미리 나누어두고 각 분할에 하나의 프로세스를 적재해 실행시킬 수 있게 한다.
  • 분할의 크기는 동일하게 할 수도 있고 서로 다르게 할 수도 있다. 하지만 모두 하나의 분할에는 하나의 프로그램만을 적재할 수 있다. 
  • 동시에 메모리에 올릴 수 있는 프로그램의 수가 고정되어 있으며 수행 가능한 프로그램의 최대 크기 또한 제한된다는점에서 융통성이 떨어진다.
  • 외부조각내부조각이 발생할 수 있다.

※ 외부조각 : 어떠한 프로그램에게도 배정되지 않은 빈 공간임에도 현재 상태에서 사용될 수 없는 작은 분할

※ 내부조각 : 프로그램의 크기보다 분할의 크기가 큰 경우 해당 분할에 프로그램을 적재하고 남는 메모리 공간

 

 

가변분할 방식

  • 메모리에 적재되는 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변하는 방식을 말한다.
  • 내부조각은 발생하지 않으나, 외부조각이 발생할 가능성이 있다.
  • 물리적 메모리 내 가용 공간 중 어떤 위치에 올릴 것인지 결정하는 동적 메모리 할당 문제(dynamic storage-allocation problem)가 존재한다.
  • 연속할당 기법에서는 가용 공간의 효율적 관리를 위해 이미 사용 중인 메모리 공간과 사용하고 있지 않은 가용 공간에 대한 정보를 유지하고 있다. 
  • 동적 메모리 할당 문제를 해결하기 위한 대표적인 방법으로 세 가지가 있다.
    1. 최초적합(first-fit) 방법
      • 가용 공간을 차례대로 살펴보면서 프로그램의 크기 이상인 가용 공간이 최초로 발견되면 그 공간에 프로그램을 올리는 방법
      • 가용 공간을 모두 탐색하지 않으므로 시간적인 측면에서 효율적이다.
    2. 최적적합(best-fit) 방법
      • 크기가 n 이상인 가장 작은 가용 공간을 찾아 프로그램을 할당하는 방법
      • 가용 공간이 정렬되어 있지 않은 경우 모두 탐색해야 하므로 시간적 오버헤드가 발생하고 다수의 매우 작은 가용 공간들이 생성될 수 있다는 단점이 있다.
      • 공간적인 측면에서는 효율적이다.
    3. 최악적합(worst-fit) 방법
      • 가용 공간 중에서 가장 크기가 큰 곳에 프로그램을 할당하는 방법
      • 최적적합 방법과 마찬가지로 시간적 오버헤드가 발생한다. 또한 상대적으로 더 큰 프로그램을 담을 수 있는 가용 공간을 빨리 소진한다는 문제점이 있다.
  • 가변분할 방식의 외부조각 문제를 해결하기 위한 방법으로 컴팩션(compaction)이 있다.
    • 물리적 메모리 중에서 프로세스에 의해 사용 중인 메모리 영역을 한쪽으로 몰고 가용 공간들을 다른 한쪽으로 모아서 하나의 큰 가용 공간을 만드는 방법

 

2) 불연속할당 기법

  • 하나의 프로세스가 물리적 메모리의 여러 위치에 분산되어 올라갈 수 있는 메모리 할당 기법
  • 세 가지 기법이 존재한다.
    1. 페이징 기법 : 하나의 프로그램을 분할하는 기준에 따라 동일한 크기로 나누어 메모리에 올리는 기법
    2. 세그먼테이션 기법 : 크기는 일정하지 않지만 의미 단위로 나누어 메모리에 올리는 기법
    3. 페이지드 세그먼테이션 기법 : 세그먼테이션을 기본으로 하되 이를 다시 동일 크기의 페이지로 나누어 메모리에 올리는 기법

 

4. 페이징 기법

프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 페이지들을 저장하는 방식

페이징 기법

  • 프로세스의 주소 공간 전체를 물리적 메모리에 한꺼번에 올릴 필요는 없다.
  • 물리적 메모리를 페이지와 동일한 크기의 프레임(frame)으로 미리 나누어둔다.
  • 연속할당에서 발생했던 동적 메모리 할당 문제가 발생하지 않는다.
  • 논리적 주소를 물리적 주소로 변환하는 작업은 페이지 단위로 이루어져야 한다.
  • 모든 프로세스가 각각의 주소 변환을 위한 페이지 테이블(page table)을 가지며, 이 테이블은 프로세스가 가질 수 있는 페이지 개수만큼 주소 변환 엔트리를 가지고 있게 된다.
  • 외부조각은 발생하지 않으나 내부조각이 발생할 가능성은 있다.

 

1) 주소 변환 기법

 

페이지 테이블을 이용한 주소 변환

 

  • CPU가 사용하는 논리적 주소를 페이지 번호(p)와 페이지 오프셋(d)으로 나누어 주소 변환에 사용한다.
  • 페이지 번호는 페이지 테이블 접근 시 인덱스(index)로 사용되고, 해당 인덱스의 항목(entry)에는 그 페이지의 물리적 메모리상의 기준 주소(base address), 즉 시작 위치가 저장된다.
  • 페이지 오프셋은 하나의 페이지 내에서의 변위(displacement)를 알려준다.
  • 따라서 기준 주소값에 변위를 더함으로써 요청된 논리적 주소에 대응하는 물리적 주소를 얻을 수 있다.

 

2) 페이지 테이블의 구현

TLB에 의한 페이징 기법의 주소 변환

  • 페이지 테이블은 물리적 메모리에 위치한다.
  • 현재 CPU에서 실행 중인 프로세스의 페이지 테이블에 접근하기 위해 운영체제는 2개의 레지스터를 사용한다.
    1. 페이지 테이블 기준 레지스터 (page-table base register)
      -> 메모리 내에서의 페이지 테이블의 시작 위치 보관
    2. 페이지 테이블 길이 레지스터 (page-table length register)
      -> 페이지 테이블의 크기 보관
  • 페이징 기법에서의 메모리 접근 연산은 주소 변환을 위해 페이지 테이블에 접근하는 것과, 변환된 주소에서 실제 데이터에 접근하는 것, 이렇게 두 번의 메모리 접근을 필요로 한다. -> 메모리에 한 번 접근하기 위해 매번 메모리에 두 번 접근하는 오버헤드가 따른다.
  • 이러한 오버헤드를 줄이고 메모리의 접근 속도를 향상시키기 위해 TLB(Translation Look-Aside Buffer)라고 불리는 고속의 주소 변환용 하드웨어 캐시가 사용되기도 한다.
    • 빈번히 참조되는 페이지에 대한 주소 변환 정보만을 담는다.
    • 요청되는 페이지에 대한 주소 변환 정보가 TLB에 들어있을 수도 있고 그렇지 않을 수도 있다.
    • 문맥교환 시 이전 프로세스의 주소 변환 정보를 담고 있던 TLB 내용은 모두 지워버려야 한다.
  • 페이지 테이블은 페이지 번호에 따라 주소 변환 정보가 순차적으로 들어 있지만, TLB는 모든 페이지에 대한 정보가 없기 때문에 페이지 번호와 이에 대응하는 프레임 번호가 쌍으로 저장되어야 한다. 
  • TLB의 모든 항목을 다 찾아봐야 하는 오버헤드를 줄이기 위해 TLB 구현에는 일반적으로 병렬탐색이 가능한 연관 레지스터(associative register)를 사용한다. 

※병렬탐색 : TLB 내의 모든 항목을 동시에 탐색할 수 있는 기능

 

3) 계층적 페이징

  • 페이지 테이블에 사용되는 메모리 공간의 낭비를 줄이기 위해 사용하는 N단계 페이징 기법이 존재한다.
  • 2단계 페이징일 경우 주소 변환을 위해 외부 페이지 테이블(outer page table)과 내부 페이지 테이블(inner page table)의 두 단계에 걸친 페이지 테이블을 사용한다.
  • 사용되지 않는 주소 공간에 대해서는 외부 페이지 테이블의 항목을 NULL로 설정하며, 여기에 대응하는 내부 페이지 테이블을 생성하지 않는다. 
  • 페이지 테이블을 위해 사용되는 메모리 공간을 줄여 공간적인 이득을 볼 수 있지만, 주소 변환을 위해 접근해야 하는 페이지 테이블의 수가 증가하므로 시간적인 손해가 뒤따른다.
  • TLB를 사용하면 시간적인 오버헤드를 줄일 수 있다.

2단계 페이징에서의 주소 변환

 

4) 역페이지 테이블

- 물리적 메모리의 페이지 프레임 하나당 페이지 테이블에 하나씩의 항목을 두는 방식
- 물리적 주소에 대해 페이지 테이블을 만드는 것 
- 각 프로세스마다 페이지 테이블을 두지 않고, 시스템 전체에 페이지 테이블을 하나만 두는 방법

역페이지 테이블을 이용한 주소 변환

 

  • 페이지 테이블의 각 항목은 어느 프로세스의 어느 페이지가 이 프레임에 저장되었는지의 정보를 보관하고 있다.
  • 페이지 테이블의 각 항목은 프로세스 번호(pid)와 그 프로세스 내의 논리적 페이지 번호(p)를 담고 있다.
  • 물리적 주소로부터 논리적 주소를 얻기 수월한 구조로 되어 있다. 
  • 그 주소를 담은 페이지가 물리적 메모리에 존재하는지 여부를 판단하기 위해 페이지 테이블 전체를 다 탐색해야 하는 어려움이 있다.
  • 역페이지 테이블은 일반적으로 메모리에 유지하는 대신 연관 레지스터(associative register)에 보관해 테이블 전체 항목에 대한 병렬탐색을 가능하게 함으로써 시간적 효율성을 꾀한다.

 

5) 공유 페이지

- 공유 코드 : 메모리 공간의 효율적인 사용을 위해 여러 프로세스에 의해 공통으로 사용될 수 있도록 작성된 코드
- 공유 페이지란 공유 코드를 담고 있는 페이지를 말한다.

 

  • 공유 페이지는 여러 프로세스에 의해 공유되는 페이지이므로 물리적 메모리에 하나만 적재되어야 한다.
  • 공유 페이지는 그 페이지를 공유하는 모든 프로세스의 주소 공간에서 동일한 페이지 번호를 가져야 한다.

공유 페이지의 예 (코드 1, 코드 2, 코드 3이 공유 코드)

 

6) 메모리 보호

  •  페이지 테이블의 각 항목에는 메모리 보호를 위한 보호비트(protection bit)와 유효-무효 비트(valid-invalid bit)를 두고 있다. 
  • 보호비트
    • 각 페이지에 대한 접근 권한의 내용이 담겨 있다.
    • 각 페이지에 대한 '어떠한' 접근을 허용하는지의 정보가 저장된다.
    • 각 페이지에 대해 읽기-쓰기/읽기전용 등의 접근 권한을 설정하는 데에 사용된다.
  • 유효-무효 비트
    • 해당 페이지의 내용이 유효한지에 대한 내용을 담고 있다.
    • '유효'로 세팅
      - 해당 메모리 프레임에 그 페이지가 존재함을 뜻하며 접근이 허용된다.
    • '무효'로 세팅
      - 프로세스가 그 주소 부분을 사용하지 않거나, 해당 페이지가 물리적 메모리에 올라와 있지 않고 백킹스토어에 존재해 해당 메모리 프레임에 유효한 접근 권한이 없다는 의미를 지닌다.

 

 

5. 세그먼테이션

프로세스의 주소 공간을 의미 단위의 세그먼트(segment)로 나누어 물리적 메모리에 올리는 기법

 

  • 세그먼트의 크기는 각각 다를 수 있다.
  • 크기가 균일하지 않은 세그먼트들을 메모리에 적재하는 부가적인 관리 오버헤드가 뒤따르게 된다.
  • 논리적 주소가 <세그먼트 번호, 오프셋>으로 나뉘어 사용된다.
    • 세그먼트 번호
      - 해당 논리적 주소가 프로세스 주소 공간 내에서 몇 번째 세그먼트에 속하는지를 나타낸다.
    • 오프셋
      - 그 세그먼트 내에서 얼마만큼 떨어져 있는지에 대한 정보를 나타낸다.
  • 주소 변환을 위해 새그먼트 테이블을 사용하는데, 각 항목은 기준점(base)과 한계점(limit)을 가지고 있다.
    • 기준점
      - 물리적 메모리에서 그 세그먼트의 시작 위치를 나타낸다.
    • 한계점
      - 그 세그먼트의 길이를 나타낸다.
  • 세그먼트 테이블 기준 레지스터와 세그먼트 테이블 길이 레지스터가 사용된다.
    • 세그먼트 테이블 기준 레지스터
      - 현재 CPU에서 실행 중인 프로세스의 세그먼트 테이블이 메모리의 어느 위치에 있는지 그 시작 주소를 담고 있다.
    • 세그먼트 테이블 길이 레지스터
      - 그 프로세스의 주소 공간이 총 몇개의 세그먼트로 구성되는지, 즉 세그먼트의 개수를 나타낸다.
  • 논리적 주소를 물리적 주소로 변환하는 과정은 다음과 같다.
    1. 요청된 세그먼트 번호가 세그먼트의 개수보다 작은 값인가?
      - 그렇지 않다면 이는 존재하지 않는 세그먼트에 대한 접근 시도이므로 예외상황을 발생시킨다.
    2. 논리적 주소의 오프셋값이 그 세그먼트의 길이보다 작은 값인가?
      - 세그먼트 길이를 넘어서는 오프셋 위치에 대한 접근 시도라면 예외상황을 발생시킨다.

세그먼테이션 기법에서의 주소 변환

 

  • 페이징 기법과 마찬가지로 세그먼트 테이블의 각 항목에 보호비트와 유효비트가 존재한다.
    • 보호비트 : 각 세그먼트에 대해 읽기/쓰기/실행 등의 권한이 있는지를 나타낸다.
    • 유효비트 : 각 세그먼트의 주소 변환 정보가 유효한지(해당 세그먼트가 현재 물리적 메모리에 적재되어 있는지)를 나타낸다.
  • 세그먼테이션 기법에도 공유 세그먼트 개념이 존재한다.
  • 공유 세그먼트는 이 세그먼트를 공유하는 모든 프로세스의 주소 공간에서 동일한 논리적 주소에 위치해야 한다.

공유 세그먼트의 예

 

6. 페이지드 세그먼테이션

  • 페이징 기법과 세그먼테이션 기법의 장점만을 취하는 주소 변환 기법이다.
  • 프로그램을 의미 단위의 세그먼트로 나누지만 반드시 동일한 크기 페이지들의 집합으로 구성되어야 한다. 
  • 물리적 메모리에 적재하는 단위는 페이지로 한다. 
  • 즉, 페이지드 세그먼테이션 기법은 하나의 세그먼트 크기를 페이지 크기의 배수가 되도록 함으로써 세그먼테이션 기법에서 발생하는 외부조각의 문제점을 해결하며, 동시에 세그먼트 단위로 프로세스 간의 공유나 프로세스 내의 접근 권한 보호가 이루어지도록 함으로써 페이징 기법의 약점을 해소한다. 
  • 주소 변환을 위해 외부의 세그먼트 테이블과 내부의 페이지 테이블, 이렇게 두 단계의 테이블을 이용한다. 
  • 하나의 세그먼트가 여러 개의 페이지로 구성되므로 각 세그먼트마다 페이지 테이블을 가지게 된다. 

 

Reference

 

운영체제와 정보기술의 원리 - 교보문고

이 책은 총 10장으로 구성되어 있다.1장 ‘컴퓨터 및 정보기술의 역사’에서는 운영체제를 설명하기에 앞서 정보기술의 원리와 철학에 대해 정의하고, 컴퓨터와 정보기술 분야의 역사를 간략히

www.kyobobook.co.kr

 

반응형

'CS > OS' 카테고리의 다른 글

[OS] 08. 가상메모리  (0) 2022.01.01
[OS] 프로세스와 스레드  (0) 2021.12.29
[OS] 06. CPU 스케줄링  (0) 2021.12.26
[OS] 스핀락, 뮤텍스, 세마포어  (0) 2021.12.22
[OS] 공유 자원 접근 문제  (0) 2021.12.22

댓글