티스토리 뷰
컴퓨터 시스템 구조
아래에 간단하게 설명
Main Memory
- CPU의 작업 공간
Device controller
- 해당 I/O 장치유형을 관리하는 일종의 작은 CPU
- 각 device의 내부를 통제하는 것은 CPU가 아닌 각 device controller의 역할
- 제어 정보를 위해 control register, status register을 가짐.
- local buffer 가짐.
- I/O는 실제 device와 local buffer 사이에서 일어나고, I/O가 끝났을 경우 device controller는 interrupt로 CPU에 그 사실을 알림.
- 만약 CPU가 instruction을 수행하다가 프로그램이 disk에서 데이터를 읽어와야 하는 경우엔 CPU가 직접 disk에 접근하는 것이 아니라 disk controller한테 일을 시키는 것임.
- Device driver: OS 코드 중 각 장치 별 처리 루틴
-> Software
Device controller
-> Hardware
Local buffer
- 각 device의 작업 공간
CPU
- CPU의 처리속도가 I/O device의 처리 속도보다 매우 빠름.
- CPU안에는 메모리보다 더 빠르면서 정보를 저장할 수 있는 레지스터가 있음.
- CPU는 매 clock cycle마다 메모리에서 instruction(명령어)를 하나씩 읽어서 실행.
- CPU는 하나의 instruction이 끝나면 interrupt line을 체크함. 이때 timer가 interrupt를 걸어왔으면 CPU는 하던 일을 멈추고 제어권이 사용자 프로그램으로부터 OS한테 자동으로 넘어감.
Interrupt line
- CPU가 instruction을 실행하다가 키보드 입력 등 I/O device들의 입출력을 interrupt line을 통해 알 수 있음.
mode bit
- 사용자 프로그램의 잘못된 수행으로 다른 프로그램 및 운영체제에 피해가 가지 않도록 하기 위한 보호 장치
- 값이 1인 경우 -> 사용자 프로그램을 수행 중인 상태로, 제한된 instruction만 CPU에서 실행할 수 있음.
=> 사용자 모드 - 값이 0인 경우 -> OS 코드를 수행 중인 상태로, 무슨 일이든 다 할 수 있게 정의되어 있음(메모리, I/O device 접근 등)
=> 모니터 모드 - 보안을 해칠 수 있는 중요한 명령어는 모니터모드에서만 수행 가능한 특권 명령으로 규정.
- interrupt나 exception 발생 시 하드웨어가 mode bit을 0으로 바꿈.
사용자 프로그램에게 CPU를 넘기기 전에 mode bit을 1로 바꿈.
Timer
- 특정 프로그램이 CPU를 독점하는 것을 막는 역할.
- 운영체제가 사용자 프로그램한테 CPU를 넘겨줄 땐 timer에 정해진 시간을 할당 후에 넘겨줌.
-> 정해진 시간이 지나면 운영체제에게 제어권이 넘어가도록 interrupt를 발생시킴. - CPU의 time sharing을 구현할 때 이용됨.
DMA(Direct Memory Access) Controller
- I/O device가 너무 많이 interrupt를 걸어 CPU가 방해를 받는 것을 막는 역할.
-> 매번 interrupt를 걸지 않고 한 번씩만 걸어서 더욱 효율적으로 사용 가능하게 함. - 메모리에 접근할 수 있음.
- 빠른 입출력 장치를 메모리에 가까운 속도로 처리하기 위해 사용.
- device controller가 buffer에 일정량의 data가 쌓이면 CPU의 중재 없이 device의 buffer storage 내용을 메모리에 block 단위로 직접 전송.
=> 결국 CPU는 PC*가 가리키는 instruction을 수행하며, 그 instruction 중 I/O device를 접근해야 하는 상황이 되면 device driver를 통해서 읽고 쓰는 등의 명령을 시킴. CPU는 직접 일을 하는 것이 아닌 메모리에 있는 instruction 지시를 받아서 일을 할 뿐임.
*PC(Program Counter): 다음 번에 어디 있는 instruction을 실행할지에 대한 주소를 가지고 있는 레지스터
입출력(I/O)의 수행
모든 입출력 명령은 특권 명령이기 때문에 사용자 프로그램이 직접 I/O를 하지 못하고 운영체제를 통해서만 I/O 장치에 접근 가능.
그렇다면 사용자 프로그램은 어떻게 I/O를 하는가?
-> 시스템콜(system call)을 통해 운영체제의 커널에게 부탁함.
시스템콜
-> 사용자 프로그램이 운영체제의 커널 함수를 호출하는 것.
( 커널 함수: 운영체제의 주요 역할을 수행하는 함수들의 집합)
- 사용자 프로그램이 운영체제에게 I/O 요청
- trap을 사용하여 인터럽트 벡터의 특정 위치로 이동
- 제어권이 인터럽트 벡터가 가리키는 인터럽트 서비스 루틴으로 이동.
- 올바른 I/O 요청인지 확인 후 I/O 수행
- I/O 완료 시 제어권을 시스템콜 다음 명령으로 옮김.
I/O를 하기 위해 두 가지 종류의 interrupt가 걸림.
-> 처음에 사용자 프로그램이 I/O를 요청하기 위해서 OS한테 시스템콜을 해줌.(소프트웨어 인터럽트)
-> OS가 일을 시키고 그 일이 다 끝나면 하드웨어 인터럽트를 통해 알려줌.
인터럽트
인터럽트 당한 시점의 레지스터와 program counter를 저장한 후 CPU의 제어를 인터럽트 처리 루틴에 넘김.
- interrupt (하드웨어 인터럽트): 하드웨어가 발생시킨 interrupt
- trap (소프트웨어 인터럽트)
- Exception: 프로그램이 오류를 범한 경우
- System Call: 프로그램이 커널 함수를 호출하는 경우
현대의 운영체제는 인터럽트에 의해 구동됨.
-> CPU 독점을 막기 위한 time interrupt
-> 요청한 I/O가 다 끝난 것을 알려주기 위해, 또는 키보드의 입력 등을 알려주기 위해 I/O controller가 interrupt를 걺.(시스템콜)
=> 즉, 운영체제는 CPU를 사용할 일이 없고 interrupt가 들어올때만 CPU가 운영체제한테 넘어감. 평소엔 항상 사용자 프로그램이 쓰고있음.
interrupt 관련용어
- 인터럽트 벡터: 해당 인터럽트의 처리 루틴 주소를 가지고 있음.
- 인터럽트 처리 루틴(= interrupt service routine, interrupt handler): 해당 interrupt를 처리하는 커널 함수.
동기식 입출력과 비동기식 입출력
- 동기식 입출력 (Synchronous I/O)
- I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에 넘어감.
구현 방법 1
- I/O가 끝날 때까지 CPU 낭비
- 매 시점 하나의 I/O만 일어날 수 있음.
구현 방법2
- I/O가 완료될 때까지 해당 프로그램에게서 CPU 뺏음
- I/O 처리를 기다리는 줄에 그 프로그램을 줄 세움.
- 다른 프로그램에게 CPU 줌. - 비동기식 입출력 (Acynchronous I/O)
- I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에 즉시 넘어감.
=> 두 경우 모두 I/O의 완료는 인터럽트로 알려줌.
서로 다른 입출력 명령어
- I/O를 수행하는 special한 instruction에 의해 (일반적인 경우 -> 좌측)
- 메모리만 접근하는 instruction과 I/O device만 접근하는 instruction으로 나눠져있음. - Memory Mapped I/O에 의해 (우측)
- I/O device에 메모리 주소를 준 뒤 메모리 접근하는 instruction을 통해 I/O 가능.
저장장치 계층구조
위에 있을 수록 속도가 빠르고, 단위 공간 당 가격이 비싸므로 용량이 작음.
- Primary
- CPU에서 직접 접근 가능 -> 바이트 단위로 접근이 가능해야 CPU 접근 가능.
- 휘발성 (Volatility): 컴퓨터가 종료되면 데이터가 사라짐. - Secondary
- CPU가 직접 접근해서 처리하지 않음.
Caching: faster storage system으로 정보를 복사
-> 보통 재사용을 목적으로 사용.
프로그램의 실행
보통 프로그램은 실행파일 형태로 하드디스크에 저장되어있음. 파일을 실행시키면 메모리로 올라가서 프로세스가 됨. 다만 이때 physical memory에 바로 올라가는 것이 아니라 virtual memory를 거침.
Virtual memory
- 프로그램을 실행시키면 독자적인 Address space가 형성됨.
- 각 Address space는 stack, data, code로 구성됨.
stack -> code가 함수구조로 되어있기 때문에 함수를 호출하거나 리턴할 때 데이터를 쌓았다가 꺼내는 용도로 사용.
data -> 변수같은 자료구조
code -> CPU에서 실행할 기계어(instruction)코드 - 이 주소공간은 실제로 존재하는 공간이 아님.
Physical Memory
- User영역과 커널영역으로 나눠져있음.
프로그램을 실행시켰을 때 만들어지는 주소 공간을 전부 물리적인 메모리에 다 올리지는 않음(메모리 낭비)
당장 필요한 부분만 유저 영역에 올리고 나중에 사용안되면 메모리에서 쫓아냄. 이때 당장 필요하지 않은 부분은 디스크의 Swap area라는 곳에 내려놓음.
Swap area
- 전원이 꺼지면 의미없는 정보가 됨(프로세스가 종료되어 메모리에 있는 내용도 사라짐)
- 메모리 공간의 한계로 인해 연장 공간으로 사용됨.
File system
- 비휘발성(전원이 꺼져도 정보가 사라지지 않음)용도로 사용.
Address translation(주소 변환)
각 프로그램마다 0번지부터 시작하는 주소 공간이 있는데 물리적인 메모리도 0번지부터 시작하는 주소 공간임. 예를 들어, Virtual memory에서 1000번지인 경우에 Physical memory에서는 3000번지에 올라가듯이 주소가 바뀜. 이를 주소 변환이라고 하는데, 이처럼 메모리 주소 변환을 해주는 하드웨어 장치가 있음. 이는 운영체제가 하는 것이 아닌 하드웨어의 지원을 받아서 해줌.
커널 주소 공간의 내용
code
커널 코드들이 들어있음.
-> 시스템콜(소프트웨어 인터럽트) 처리 코드
-> 인터럽트 처리 코드
(운영체제는 인터럽트가 들어오면 CPU를 얻게 되는데, 각각의 인터럽트마다 어떤 일을 처리해야하는지 커널 코드에 함수형태로 구현되어있음.)
-> 자원 관리(운영체제의 역할)를 위한 코드
-> 편리한 서비스 제공을 위한 코드
data
운영체제가 사용하는 자료 구조들이 정의되어있음.
시스템 안에 프로그램이 하나 돌아가면 그 프로그램을 관리하기 위한 자료구조가 운영체제 커널에 만들어짐 => PCB
stack
운영체제도 함수 구조로 짜여져있기 때문에 함수를 호출하거나 리턴할 때 stack영역을 사용해야 함.
운영체제의 코드는 여러 프로그램들이 요청에 따라 불러 쓸 수 있음. A, B프로그램 모두 시스템콜 가능하므로 각각의 사용자 프로그램마다 커널 stack을 따로 둠.
사용자 프로그램이 사용하는 함수
- 사용자 정의 함수(직접 작성한 함수)
-> 자신의 프로그램에서 정의한 함수 - 라이브러리 함수
-> 자신의 프로그램에서 정의하지 않고 갖다 쓴 함수
-> 자신의 프로그램의 실행 파일에 포함되어 있음.
=> 위 두 종류 함수는 프로세스 Address space의 code영역에 포함되어있음.
- 커널 함수
-> 운영체제 프로그램의 함수
-> 커널 함수의 호출 = 시스템콜
=> 시스템콜을 통해 내 프로그램에서 가져다 쓸 수 있지만 프로그램 안이 아닌 커널 코드 안에 있음.
프로그램의 실행(timer등 배제)
user mode
-> 프로그램이 직접 CPU를 잡고 있으면 user mode에 있다고 함.
-> 사용자 정의함수를 호출해서 쓸 수 있음(여전히 user mode)
-> 라이브러리 함수 호출 가능(여전히 자신의 주소공간에 있는 코드를 실행함)
kernel mode
-> system call은 kernel 주소 공간에 있는 코드를 실행.
'CS > 운영체제' 카테고리의 다른 글
[반효경 교수님 - 운영체제] CPU Scheduling (0) | 2022.05.17 |
---|---|
[반효경 교수님 - 운영체제] Process Management (0) | 2022.05.14 |
[반효경 교수님 - 운영체제] Process (0) | 2022.05.14 |
[반효경 교수님 - 운영체제] Introduction to Operating Systems (0) | 2022.05.09 |
- Total
- Today
- Yesterday