core.ewha.ac.kr/publicview/C0101020140314151238067290?vmode=f
io 작업, exception 이 났을때 process는 trap(interrupt)을 걸어 os 에게 cpu 를 넘긴다.
synchronous IO :
사용자 process 에서 io 가 발생하면 cpu 가 os 에게 넘어감
os 는 io 명령을 수행하고 io 응답이 올 때 까지 기다림(cpu 는 아직도 os 에게 있음)
io 응답이 오면 그제서야 사용자 process memory 에 결과를 넣고
사용자 process 에게 cpu 를 돌려줌.
....cpu 낭비가 어마무시하군. 또한 매시점 하나의 io 만 일어나기 때문에 다른 io 디바이스들도 노는 꼴이 됨.
그래서 io 명령을 수행한 후 응답을 기다리지 않고, 다른 process 에게 cpu 를 넘겨준다고 함.
cpu (와 io 디바이스들)가 놀지 않게 하기 위해.
io 응답이 오면 사용자 process memory 에 결과를 넣고
(다른, 혹은 io를 발생시킨) process 에게 cpu 를 돌려줌.
asynchronous IO :
A라는 사용자 process 에서 io 가 발생하면 cpu 가 os 에게 넘어감
os 는 io 명령을 수행하고, io 응답이 오는 걸 기다리지 않고 바로 A process 에게 다시 cpu 를 넘김
io 응답이 오면 interrupt 가 걸리고, os 는 해당 처리를 한 다음 다시 A process 에게 cpu 를 넘김.
JAVA 프로그램을 예로 들어 쉽게 설명하자면,
동기식 입출력은 io 를 요청한 후 process가 멈춤. io 응답이 오면 그제서야 process가 계속됨.
여기서 process 가 계속 멈춰있으면 cpu 가 놀게 되니까, 그 때 다른 process 에게 cpu 를 줄 수 있음.
비동기식 입출력은 io 를 요청한 후 응답이 오든 말든 process 는 다음 명령을 계속 수행함.
io 응답이 오면 응답 결과를 가지고 다시 일처리를 하겠지.
컴퓨터에 DMA(Direct Memory Access) 라는 장치가 있음.
io 디바이스들이 하도 cpu 에 interrupt 를 여러번 거니까 cpu 효율이 나빠짐.
DMA 는 cpu 가 받는 io interrupt 들을 자신이 받아 미리 처리하고(memory 에 io 응답값을 넣는 등)
cpu 에게는 "일을 내가 거의 끝내놨다. 너는 마무리 작업을 해라" 라고 말하며
cpu 에게 한 번만 interrupt 를 걸어줌.
이렇게 cpu 의 부담을 줄여주는 것이 DMA.
예를 들어 키보드의 키 하나를 누르면 1byte 정보가 키보드 버퍼에 쌓이고
키보드의 device controller 가 cpu 에 interrupt 를 걸어
메모리 내로 방금 생성한 1byte 정보를 복사하라고 요청
이런 방식으로 키보드를 사용하면 수많은 interrupt 들이 생성될텐데,
이 interrupt 들이 계속 cpu 를 방해하면 성능이 떨어짐.
DMA 는 이런 상황에서 필요함.
DMA 는 키보드에서 생성한 1byte 에 대한 interrupt 를 자신이 받아서
메모리에 직접 정보를 넣음.
메모리에 넣은 정보가 특정 단위(페이지 혹은 블럭)를 넘어서면 그제서야 DMA 가
cpu 에게 "네가 할 일 내가 미리 끝내놓음. 나머지 작업 네가 처리하셈" 라고 말하며
cpu 에게 한 번 interrupt 를 걸어줌.
DMA 덕분에 cpu 가 interrupt 당하는 빈도가 줄어 성능이 향상됨.
DMA 는 메모리에 직접 접근이 가능함(그래서 io 응답 처리가 가능함)
아래는 프로그램이 어떻게 실행되는지 그 절차를 설명함.
- 프로그램은 실행파일 형태(binary)로 disk 에 저장되어 있음.
- 프로그램이 실행되면 프로그램의 binary 가 memory 에 올라가게 됨.
- memory 에 올라갈 때, 각 프로그램들은 memory에 각자의 memory 공간을 할당받게 됨.
(프로그램이 memory 에 올라가 있어야 cpu 가 실행할 수 있으니까)
- memory 공간은 주소를 갖고 있음
- 각 프로그램들이 할당받은 공간의 주소는10, 예를들어
프로그램A는 2553~6754 이고 프로그램 B는 88552~91502, 12204~53582
이렇게 예쁘지 않은 주소 공간임. 게다가 나란히 존재하지 않고 쪼개져 있을 가능성이 농후함
- 하지만 각 프로그램 입장에서는 아주 예쁘게 0부터 1024 처럼 정렬된 공간처럼 보임.
이것이 virtual memory
- 프로그램은 자신을 실행시키기 위해 할당받은 메모리 공간에 code, data, stack 영역으로 나눈 후
각 영역의 역할에 맞게 사용.
- code : cpu 에서 실행할 기계어 코드를 넣음.
- data : code 에서 실행할 전역변수 등을 넣는 영역으로 사용.
- stack : code 가 동작할 때 사용하는 stack 영역(함수를 실행하는 데 사용하는 stack 영역) 으로 사용.
- 흔히 쓰이는 JAVA 프로그램의 경우 할당받은 메모리 공간을 메소드, 스택, 힙 영역으로 나눠서 사용.
[여기] 링크에서 구체적으로 확인 가능.
- 각 프로그램이 할당받은 메모리 공간이 모두 memory 를 차지하고 있지 않음(모두 메모리에 올라가 있지 않음)
- 각 프로그램에서 실제 사용해야 하는 부분만 메모리에 올림.
다 올리면 프로그램에서 안 사용하는 부분까지 올라가게 되어 메모리가 낭비되니까.
- 그럼 메모리 공간에 올라가지 않은 나머지 프로그램부분은 어디에 있을까? 아직 disk 에 있다.
- 즉, disk 에서 프로그램이 실행을 위해 필요한 부분만 읽어 메모리에 넣은 다음 cpu 를 통해 실행시키는 것.
- 다르게 말하면, 메모리에 올라가 있는 프로그램 부분 중에 안 사용하는 부분은 메모리에서 내려와서
다시 disk 로 돌아감
- 커널 역시 프로그램(상시 돌아가는 process)이기 때문에 자신의 메모리 주소 공간을 갖고 있음
위 이미지에서 흰 색 박스 부분.
커널은 os 라서 중요하니까
커널의 주소 공간 내용을 구체적으로 살펴보자.
커널의 코드 부분에는 다음과 같은 코드들이 들어있음.
- 각 interrupt 를 처리하기 위한 코드(interrutpt 처리 루틴)
- 자원 관리를 위한 코드
- 사용자에게 제공하는 인터페이스 코드
data 부분에는 cpu, memory 등 자원 관리하기 위한 자료구조 들이 들어있음.
또한 동작하는 process 들을 관리하기 위한 자료구조(PCB) 들이 들어있음.
예를 들어 process A 가 cpu 를 얼마나 썼는지, 다음 process 에게 메모리는 얼마나 줘야 하는지 등
이걸 보고 PCB(Process Control Block) 이라고 함.
즉 프로그램마다 PCB 가 하나씩 만들어져서 os 가 관리함.
그리고 그것이 (위 그림처럼) data 영역에 들어있음.
os(kernel) 역시 함수 구조로 짜여있기 때문에 함수나 return 등의 구조를 사용하기 위한 stack 영역을 사용.
사용자 process 들이 os 에 system call 을 하면 그것을 각 process 당 커널 스택으로 정리함.
예를 들어 process A 가 system call 을 하고 process B 역시 system call 을 하면
그것들을 각 process 에 맞게 process A 의 커널스택, process B 의 커널스택으로 관리한다고 함.
... 솔직히 이해는 안 가는데 자세한 내용을 뒤에서 한다고 함.
프로그램은 함수로 이루어짐.
C로 짜든 JAVA 로 짜든 프로그램은 함수로 구성됨.
프로그램을 구성하는 함수는 총 세 가지 종류가 있음.
- 사용자 정의 함수 : 코드 내에 사용자가 직접 만든 함수. myfunc 같은 ㅋㅋ
- 라이브러리 함수 : 라이브러리를 통해 불러온(import) 함수 혹은 내장 함수.
- 커널 함수 : os 가 정의함, os 프로그램의 함수. 즉 system call.
예를 들어 read("/home/eyeballs/README.md") 라는 함수를 실행하면
해당 path 의 file 을 읽어달라는 명령이 실행되는데
이 때 system call 이 불림. 이 system call 에 의해 실행되는 (실질적으로 device 에 가서 읽는) 함수는
os 에서 제공해주는 함수임.
사용자 정의 함수, 라이브러리 함수는 process 가 할당받은 메모리 공간의 code 영역에 들어감.
커널 함수는 os 이 갖고 있는 kernal 메모리 공간의 code 영역에 들어감.
따라서 사용자 정의 함수, 라이브러리 함수를 실행할 때는
cpu interrupt 가 걸리지 않고 자기 메모리 공간 내에서 계속 실행이 가능
커널 함수(system call)를 실행할 때는 interrupt 가 걸림.
아래 이미지는 프로그램을 실행시키는 절차를 보여준다.
빨간색 선은 프로그램이 cpu 를 잡고 있을 때
파란색 선은 os(커널)가 cpu 를 잡고 있을 때
'Linux' 카테고리의 다른 글
[운영체제] 이화여대 반효경 교수님 수업 필기 Process2,3 (0) | 2020.10.03 |
---|---|
[운영체제] 이화여대 반효경 교수님 수업 필기 Process1 (0) | 2020.10.02 |
[운영체제] 이화여대 반효경 교수님 수업 필기 System Structure & Program Execution 1 (0) | 2020.09.26 |
[운영체제] 이화여대 반효경 교수님 수업 필기 Introduction to Operating Systems (0) | 2020.09.26 |
[Linux] 이것이 리눅스다 강의 정리 18장 (0) | 2020.09.25 |