SY 개발일지
article thumbnail

본 챕터에서는 컴퓨터 시스템에서 하드웨어가 어떻게 동작하는지, 프로그램들이 이러한 하드웨어 위에서 어떻게 돌아가는지에 대한 내용을 다룬다.

컴퓨터 시스템 구조

보통 컴퓨터를 HOST라고 부른다. CPU의 작업 영역이 메모리이고, 매 clock 사이클마다 메모리에서 instruction(기계어)을 하나씩 읽어나가면서 실행하게 된다.

각각의 I/O 디바이스들은 각각을 전담하는 작은 CPU같은 것들이 존재한다. 이것을 device controller라고 부른다. 그래서 각각의 I/O와 관련된 작업은 CPU가 아니라 device controller에서 작업을 한다. 

메인 CPU에 메인 memory 가 있듯이 디바이스들도 작업공간들이 필요한데, 이걸 local buffer라고 한다.

 

CPU안에는 메모리보다 더 빠르면서 정보를 저장할 수 있는 작은 공간이 있는데, 이를 register라고 한다.

mode bit은 현재 CPU에서 실행하고 있는 것이 운영체제인지, 아니면 사용자 프로그램인지를 구분해준다.

CPU는 항상 메모리에 있는 instruction들만 실행을 하는데, 이 instruction 하나가 실행되고 나면 다음 instruction, 즉 다음에 실행할 기계어의 주소값이 증가하고 이러한 사이클이 계속 돌아가는데, 이와중에 키보드 입력을 받거나 디스크에서 값을 가져오거나 하고 싶은데, 이럴 때 interrupt line이 작업한다. 

만약 사용자 프로그램이 무한루프에 빠지는 프로그램이라면 어떻게 해야할 것인가 ? 이럴 때 CPU가 이 프로그램에 할당되면, CPU가 다른 프로그램으로 가지 못하고 계속 CPU를 점유하게 된다. 이런 것을 막기 위해 timer가 존재한다. 즉, timer는 하나의 프로그램이 CPU를 독점하는 것을 막기 위한 것이다. 하나의 프로그램이 CPU에 할당되면 timer에 할당된 시간만큼만 CPU를 점유하고, 시간이 끝나면 타이머가 CPU에게 interrupt를 걸어 다음 기계어를 실행한다.

사용자 프로그램이 한번 CPU를 점유하게 되면 자의로 CPU를 뺏지 못한다. 그래서 timer를 통해 interrupt를 줌으로써 CPU제어권이 자동으로 운영체제에게 넘어가도록 한다.

Mode bit

  • 사용자 프로그램의 잘못된 수행으로 다른 프로그램 및 운영체제에 피해가 가지 않도록 하기 위한 보호 장치 필요
  • Mode bit을 통해 하드웨어 적으로 두 가지 모드의 operation 지원
1  사용자 모드: 사용자 프로그램 수행
0  모니터 모드: OS 코드 수행 (모니터 모드 = 커널 모드 = 시스템 모드)
  • 보안을 해칠 수 있는 중요한 명령어는 모니터 모드에서만 수행 가능한 '특권 명령'으로 규정
  • Interrupt나 Exception 발생시 하드웨어가 mode bit을 0으로 바꿈
    • mode bit이 0일때는 메모리접근 뿐만 아니라 I/O접근 등도 가능하다.
  • 사용자 프로그램에게 CPU를 넘기기 전에 mode bit을 1로 세팅
    • mode bit이 1일때는 제한된 instruction만 실행 가능하다. (보안상의 이유)

Timer

  • 정해진 시간이 흐른 뒤 운영체제에게 제어권이 넘어가도록 인터럽트를 발생시킴
  • 타이머는 매 클럭 틱마다 1씩 감소
  • 타이머 값이 0이 되면 타이머 인터럽트 발생
  • CPU를 특정 프로그램이 독점하는 것으로부터 보호
  • 타이머는 time sharing을 구현하기 위해 널리 이용됨
  • 타이머는 현재 시간을 계산하기 위해서도 사용

Device Controller

  • I/O device controller
    • 해당 I/O 장치유형을 관리하는 일종의 작은 CPU
    • 제어 정보를 위해 control register, status register를 가짐
    • local buffer를 가짐(일종의 data register)
  • I/O는 실제 device와 local buffer 사이에서 일어남
  • Device controller는 I/O가 끝났을 경우 interrupt로 CPU에 그 사실을 알림
device driver(장치 구동기): OS 코드 중 각 장치별 처리루틴  => software
device controller(장치 제어기): 각 장치를 통제하는 일종의 작은 CPU => hardware

입출력(I/O)의 수행

  • 모든 입출력 명령은 특권 명령
    • 따라서 사용자 프로그램이 I/O에게 명령을 직접 하지 못하고 운영체제를 통해서만 I/O장치에 접근 가능하다.
  • 사용자 프로그램은 어떻게 I/O를 하는가?
    • 시스템 콜(system call)
      • 사용자 프로그램은 운영체제에게 I/O 요청
    • trap을 사용하여 인터럽트 벡터의 특정 위치로 이동
    • 제어권이 인터럽트 벡터가 가리키는 인터럽트 서비스 루틴으로 이동
    • 올바른 I/O 요청인지 확인 후 I/O 수행
    • I/O 완료 시 제어권을 시스템콜 다음 명령으로 옮김

인터럽트 (Interrupt)

  • 인터럽트
    • 인터럽트 당한 시점의 레지스터와 program counter를 save한 후 CPU의 제어를 인터럽트 처리 루틴에 넘긴다
  • Interrupt (넓은 의미)
    • Interrupt (하드웨어 인터럽트): 하드웨어가 발생시킨 인터럽트
      • 보통 인터럽트 ! 하면 하드웨어 인터럽트를 의미
    • Trap (소프트웨어 인터럽트)
      • Exception: 프로그램이 오류를 범한 경우
      • System call: 프로그램이 커널 함수를 호출하는 경우
I/O를 해주기위해서 총 2가지 종류의 인터럽트가 걸림
1. 처음 사용자 프로그램이 I/O 작업을 요청하기 위해 OS에게 시스템 콜을 요청. I/O를 요청할 때 발생하는 인터럽트는 소프트웨어 인터럽트이다.

그러면 OS는 I/O에게 일을 시킨다 !!!

2. I/O 작업이 끝나면 하드웨어 인터럽트가 걸린다. I/O는 일을 다 했다고 CPU에게 알린다.
  • 인터럽트 관련 용어
    • 인터럽트 백터
      • 해당 인터럽트의 처리 루틴 주소를 가지고 있음
      • 각 인터럽트 종류마다 어디에 있는 함수를 실행해야하는지 정리해둔 곳.
    • 인터럽트 처리 루틴 (=Interrupt Service Routine, 인터럽트 핸들러)
      • 해당 인터럽트를 처리하는 커널 함수

시스템콜(System call)

  • 사용자 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출하는 것
    • I/O요청 포함 !

동기식 입출력과 비동기식 입출력

  • 동기식 입출력 (synchronous I/O)
    • I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에 넘어감
    • 구현방법 1
      • I/O가 끝날 때까지 CPU를 낭비시킴
      • 매시점 하나의 I/O만 일어날 수 있음
      • CPU뿐만 아니라 I/O도 낭비
    • 구현방법 2
      • I/O가 완료될 때까지 해당 프로그램에게서 CPU를 빼앗음
      • I/O 처리를 기다리는 줄에 그 프로그램을 줄세움
      • 다른 프로그램에게 CPU를 줌
  • 비동기식 입출력 (asynchronous I/O)
    • I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에 즉시 넘어감
  • 두 경우 모두 I/O의 완료는 인터럽트로 알려줌

DMA controller(Direct Memory Access)

  • 빠른 입출력 장치를 메모리에 가까운 속도로 처리하기 위해 사용
  • CPU의 중재 없이 device controller가 device의 buffer storage의 내용을 메모리에 block 단위로 직접 전송
  • 바이트 단위가 아니라 block 단위로 인터럽트를 발생시킴
어떤 일련의 작업에서 I/O장치가 인터럽트가 너무 많이 발생시키면 실제로 빠른 CPU가 그다지 효율성이 좋지 않게 된다. 이러한 것을 막기 위해 DMA controller를 둔다.(인터럽트가 발생하면 사용자 프로그램이 멈추고, CPU를 운영체제가 차지하고, 입력된 값을 메모리에 복사하고,, 이러한 일이 자주 발생하는데에 있어 오버헤드가 발생할 수 있어 이러한 점을 막고자 DMA를 둠)
direct-memory-access : 직접 메모리에 접근할 수 있는 컨트롤러. 그래서 CPU도 메모리에 접근 가능하고, DMA controller도 메모리에 접근 가능한데, 동시에 접근하게 되면 문제가 생길 수 있어 memory controller가 이를 관리해준다.

서로 다른 입출력 명령어

  • I/O를 수행하는 special instruction에 의해
    • 좌측 그림은 Memory에 접근할 수 있는 Instruction이 따로 있고, I/O를 위한 special instruction에 의해서 I/O를 수행하는 것이다.
  • Memory Mapped I/O에 의해
    • 우측 그림은 I/O장치도 메모리 주소에 연장 장치를 붙인 후 상이한 주소값을 통해 Memory 접근과 I/O 접근을 분리해둔 것이다. 이러한 우측 방식을 Memory mapped I/O라고 한다.

저장장치 계층 구조

  • 맨 위에는 CPU가 존재

위로 갈수록 속도가 빠르고, 가격이 비싸서 용량이 적다.

초록색 부분은 휘발성 매체이고, 붉은색 부분은 비휘발성 매체이다. 요즘에는 메인메모리도 비휘발성 매체가 들어갈 수 있는 반도체가 나오고 있다고 한다.

CPU가 접근 가능한 것을 Primary(실행 가능한), 접근 불가능한 것을 Secondary라고 한다. CPU가 접근 가능하라면 바이트 단위여야 하는데, d-ram같은 경우에는 바이트 단위로 주소를 매겨 CPU가 접근 가능한데, 하드디스크는 섹터 단위로 접근 가능하여 접근 불가능하다.

CPU 가 Instruction을 처리하려면 시간이 오래걸리는데, 그러한 속도차이를 완충시키기 위해 중간에 Cache Memory를 두고, register로 읽어들이는 작업을 한다. 근데 Cache Memory는 Main Memory보다 용량이 작기 때문에 모든 것을 다 담아두지는 못하고 당장 필요한 것만 올려놓고 사용하는데, 이러한 작업을 캐싱 Caching(다른 매체에다가 정보를 올려놓고 사용)이라고 한다. 보통 캐싱을 재사용을 목적으로 사용한다.

프로그램의 실행 (메모리 load)

프로그램은 실행파일 형태로 하드디스크에 저장되어 있는데, 이걸 실행하게 되면 메모리로 올라가면 프로세스 형태가 된다. 이때 파일시스템에서 메모리로 바로 올라가는 것이 아니라 중간에 한 단계를 더 거치게 되는데 이게 바로 가상메모리 Virtual Memory이다.

어떤 프로그램을 실행시키게 되면 그 프로그램의 주소 공간 address space 이 형성이 되는데, 이건 메모리 주소 공간이다. 이 때 주소 공간은 0부터 시작된다. 이 주소공간은 stack, data, code로 구성이 되는데, code는 CPU에서 실행할 기계어 코드를 담고, data는 변수, 자료구조들, 그리고 stack은 함수를 호출하거나 리턴할 때 데이터를 쌓거나 빼는 역할을 한다.

커널은 메모리에 항상 상주해있지만, 주소 공간은 프로그램을 실행할 때 만들어졌다가 사라지는데, 각각의 주소공간에서 필요한 부분은 사용할 때 메모리에 올렸다가 사용하지 않을 때 메모리에서 삭제시킴으로서 메모리 낭비를 막는다. 

프로그램마다 만들어지는 독자적인 주소공간은 사실 어떤 자리를 차지하고 있는 것이 아니라 어느 부분은 Physical memory에, 어느 부분은 swap area에 존재하여 virtual memory라고 불린다.

주소 변환: 각 프로그램마다 0번지부터 시작하는 주소공간이 존재하는데, 물리적인 메모리도 0번지부터 시작한다. 그래서 virtual memory내에서의 주소가 메모리에 올라갈 때 주소가 바뀌는데 이러한 것을 주소 변환 address translation이라고 한다.이러한 주소 변환은 주소 변환 계층이 존재하여 이를 해주는데, 운영체제가 해주는 것이 아니라 하드웨어의 지원(별도의 하드웨어 장치 존재)을 받아서 한다.

커널 주소 공간의 내용

시스템에 프로세스가 하나 돌아가면 그 프로세스를 관리하기 위한 운영체제를 관리하기 위한 자료구조가 필요하다. 이를 PCB(Process Control Block) 라고 하며 커널에 생성된다.

자세한 내용은 추후에 다시 설명해주신다고 하신다.

사용자 프로그램이 사용하는 함수

모든 프로그램은 함수 구조로 짜여져 있어 C언어로 작성을 하든 어떤 프로그래밍 언어로 작성을 해도 함수로 되어 있다. 이러한 고급어가 컴파일되어 기계어로 변환되더라도 그 기계어 내에서 함수에 해당하는 부분이 어디부터 어디까지인지에 대한 정보가 유지된다.

함수 (function)

  • 사용자 정의 함수
    • 자신의 프로그램에서 정의한 함수
  • 라이브러리 함수
    • 자신의 프로그램에서 정의하지 않고 갖다 쓴 함수
    • 자신의 프로그램의 실행 파일에 포함되어 있다.
  • 커널 함수
    • 운영체제 프로그램의 함수
    • 커널 함수의 호출 = 시스템 콜

사용자 정의 함수와 라이브러리 함수는 프로세스 내 주소 공간의 code에 작성되고

프로그램의 실행

user mode: 어떤 프로그램이 CPU를 잡고 있으면 user mode에 있다고 한다.

 

 

 

 

 

 

 

본 포스트는 이화여자대학교 운영체제 강의 정리본입니다.

profile

SY 개발일지

@SY 키키

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!