본문 바로가기

source-code/software

한 권으로 읽는 컴퓨터 구조와 프로그래밍

5장. 컴퓨터 아키텍처와 운영체제 - 컴퓨터는 어떻게 프로그램과 메모리를 조직적으로 관리할까

기본적인 구조 요소

가장 흔한 두 가지 컴퓨터 구조 : 폰 노이만 구조 / 하버드 구조

  • 프로세서 코어
  • 마이크로프로세서와 마이크로 컴퓨터
    • 마이크로프로세서 : 메모리와 I/O가 프로세스 코어와 같은 패키지에 들어 있지 않은 프로세서. 보통 큰 시스템에 들어가는 부품으로 쓰임
    • 마이크로 컴퓨터 : 모든 요소를 한 칩 안에 패키징 한 프로세서. 식기세척기 등에서 찾을 수 있는, 단일 칩으로 된 작은 컴퓨터.

프로시저, 서브루틴, 함수

코드를 재사용하는 주요 수단!

함수가 동작한다는 의미는? → 함수를 호출하는 부분에서 함수를 실행하고 다시 돌아올 방법이 필요.

원래 자리로 돌아오기 위해서는, 어디서 함수로 들어갔는지를 기억해야 하는데, 이 위치 = 프로그램 카운터의 값.

스택

  • 재귀
  • 트리
    • 깊이 우선 순회 / 너비 우선 순회
  • 스택
    • LIFO
    • stack overflow / stack underflow
  • 스택 프레임 - 함수가 호출될 때마다 스택에 저장되는 데이터의 모음 
    • 각 함수 호출은 반환 주소와 지역 변수를 포함하는 새로운 스택 프레임을 만듬 → 각 함수 호출 독립적 유지

인터럽트

실행 중인 프로그램을 잠깐 중단(interrupt)시켜서 주의를 기울여야 하는 외부 요소에 대응할 수 있게 만들 방법!

  • 인터럽트 시스템
    • 적절한 신호가 들어오면 CPU 실행을 잠깐 중단시킬 수 있는 핀이나 전기 연결을 포함
      • CPU가 주의를 기울여야 하는 주변장치는 인터럽트 요청을 생성
      • 프로세서는 (일반적으로) 현재 실행 중인 명령어를 끝까지 실행
      • 그 후 프로세서는 실행 중인 프로그램을 잠시 중단시키고 인터럽트 핸들러 라는 전혀 다른 프로그램을 실행
      • 인터럽트 핸들러가 필요한 작업을 다 마치고 나면, 원래 실행 중이던 프로그램이 중단된 위치부터 다시 실행을 계속
    • 고려 요소
      • 응답 시간 - 인터럽트 처리를 정해진 시간 안에 끝내야 함
      • 인터럽트를 서비스하고 나중에 다시 원래대로 돌아오기 위해, 현재 상태를 저장할 방법 필요

상대 주소 지정

여러 프로그램을 동시에 실행하는 방법? → 각 프로그램을 전환시켜 줄 수 있는 관리자 프로그램이 필요! = 운영체제(or 운영체제 커널)

OS와 OS가 관리하는 프로그램을 구분하기 위해 OS를 시스템 프로그램, 다른 모든 프로그램을 사용자 프로그램 or 프로세스 라 부름

 

프로그램을 메모리로 불러오되 각 프로그램에게 각기 다른 공간을 허용할 수 있으면, 훨씬 더 빠른 시분할 실행이 가능해짐.

but 절대 주소 지정 사용 시, 명령어 주소는 특정 메모리 주소를 가리킴.

(따라서 1000번지에서 실행되도록 만들어진 프로그램을 2000번지에 읽어 들이면 제대로 실행 X)

 → 상대 주소 지정 사용! : 명령어에 들어 있는 주소를 0부터 시작하는 위치로 해석하지 않고, 명령어의 주소를 기준으로 하는 상대적인 주소로 해석.

 

메모리 관리 장치

멀티태스킹으로 인한 오류 및 악용 방지 - 오늘날 대부분 마이크로프로세서에는 메모리 관리 장치(MMU)가 들어 있음.

MMU → 가상 주소 와 물리 주소 를 구분함

→ 프로그램은 가상 주소를 사용해 작성되고, MMU는 가상 주소를 물리 주소로 변환!

이때 가상 주소 범위는 물리적 메모리 주소보다 큰 경우가 많은데,

이는 MMU가 가상 메로리 주소를 하위(LSB 쪽) 부분(물리적 주소 범위와 같음)과

상위(MSB 쪽) 부분(페이지 테이블 이라는 RAM 영역을 통해 주소 변환)으로 나누기 때문.

 

프로그램이 물리적 메모리에 연관되지 않은 주소에 접근하면 페이지 폴트page fault 예외가 발생.

(스택 오버블로 등이 일어날 때 유용하게 사용됨)

→ 해당 예외 발생 시, OS는 실행 중인 프로그램을 중단시키는 대신, MMU가 추가 메모리를 할당하게 해서 스택 공간을 늘리고 사용자 프로그램 실행을 계속할 수 있도록 함.

 

가상 메모리

OS는 MMU를 사용해 사용자 프로그램에게 가상 메모리를 제공.

페이지 폴트 메커니즘을 통해 프로그램은 필요한 만큼(가상 메모리 주소 범위 내에서) 많은 메모리가 있다고 생각할 수 있게 됨.

 

시스템 공간과 사용자 공간

사용자 프로그램이 MMU 설정을 마음대로 바꿀 경우, MMU의 프로그램 격리 역할 수행 불가능!

여러 CPU는 이런 문제를 해결할 수 있는 추가 하드웨어 제공.

→ CPU 내에는 컴퓨터가 시스템 모드에 있는지, 사용자 모드에 있는지 결정하는 비트가 어떠한 레지스터 안에 들어있음.

(I/O 처리 명령어 등 일부 명령어는 특권 명령어이므로, 오직 시스템 모드에서만 실행 가능)

 

메모리 계층과 성능

레지스터는 마치 냉장고 같다. 냉장고에는 공간이 많지는 않지만 그 내용물에 빨리 접근할 수 있다. 주 메모리는 가게와 같다. 물건이 들어갈 공간이 더 많지만 물건을 가져오려면 시간이 더 걸린다. 대용량 저장장치는 창고와 같다. 창고는 공간이 훨씬 더 많지만 집에서 훨씬 멀리 떨어져 있다.
...
여러분은 자주 냉장고 문을 열고 물건을 하나만 가져온다. 하지만 가게를 방문할 때는 장바구니를 가져가서 물건을 좀 더 많이 채워서 가져온다. 창고에서 물건을 가져올 때는 트럭에 실어 가져온다. 컴퓨터에서 벌어지는 일도 이와 비슷하다. CPU와 주 메모리 사이에는 작은 덩어리가 오간다. 주 메모리와 디스크 사이에는 더 큰 덩어리가 오간다.
...
CPU가 메모리를 기다리느라 많은 시간을 소비해야 한다는 뜻이다. 이를 해결하기 위해 집에 있는 식품 저장고에 해당하는 캐시cache라는 하드웨서(아주 빠른 온칩 메모리)를 CPU에 추가한다. 이 식품 저장고는 가게보다 훨씬 작지만 훨씬 빠르고 프로세서와 같은 속도로 작동한다.

메모리상의 데이터 배치

대부분의 프로그램은 동적 데이터(프로그램을 실행하기 전에는 크기를 알 수 없는 데이터)를 다룸.

→ 주로 정적 데이터가 차지하는 영역의 바로 위 영역에 쌓이며, 이를 힙heap이라고 부름.

 

프로그램 실행

함수를 사용한 코드 재사용 - 관련 함수를 한데 모아 라이브러리 로 만듦.

프로그램은 라이브러리 뿐만 아니라, 여러 조각으로 나누어 개발 - 이를 하나로 엮거나 연결할 방법이 필요!

→ 각 프로그램을 링크하기 편한 형식의 매개 파일(현재 가장 유명한 매개 파일 형식인 ELF)로 나누고,

링커linker라는 특별한 프로그램을 사용해 여러 조각을 하나로 연결해 실행.

  • 정적 링크
    • 라이브러리를 단지 필요한 함수가 들어 있는 파일로 간주. 프로그램의 나머지 부분과 직접 연결해 실행 파일을 만듦
    • 여러 프로그램이 똑같은 라이브러리 사용(유용한 라이브러리) - 정적 링크 사용 시 같은 라이브러리 코드가 여러 실행 파일에 반복적으로 들어가, 귀중한 메모리를 낭비!
  • 동적 링크
    • 공유 라이브러리를 사용 - 여러 프로그램이 같은 라이브러리를 공유할 수 있게 해 줌

프로그램을 이루는 모든 부분이 하나로 합쳐져서 실행파일을 이룰 때, 런타임 라이브러리가 추가됨.

(런타임 라이브러리에 있는 명령어가 가장 먼저 실행! 이후 진입점entry point의 명령어가 실행)

런타임 라이브러리는 메모리 설정을 책임 → 스택과 힙 영역을 설정! 정적 데이터에 위치한 데이터의 초깃값 설정!