생각기록
운영체제 2차 (동기식, 비동기식 입출력 / 저장장치 계층 구조 / 프로그램의 실행 ) 본문
System Structure & Program Execution
여기까지 지난 시간 요약
컴퓨터 시스템 구조
컴퓨터 = 호스트

메모리 주소를 가르키는 register 를 프로그램 카운터 레지스터
- cpu에서 해당 주소 메모리 인스트럭션을 읽어옴
- cpu는 반복해서 프로그램 카운터 레지스터는 다음 주소를 읽어 실행
- cpu는 아주 빠른 일꾼이며 프로그램 카운터라는 레지스터가 가르키는 메모리의 인스트럭션을 읽어서 실행하는 운명 (순차적인 것만 x )
순차적인것만 있는게 아니라
함수 호출이나 if문 같은 것은 점프를 해야하는 인스트럭션도 있다.
다음 인스트럭션을 실행하기 전에 인터럽트가 들어와있는지를 체크
들어와있으면 프로그램 카운터가 들어가있는 인스트럭션을 실행하는 것이 아닌
cpu를 누가 쓰든 상관없이 제어권이 운영체제에게로 넘어간다.
운영체제는 인터럽트마다 인터럽트가 왜 걸려있는지 분별해야 한다.
운영체제 안에 커널 함수로 정의되어 있다
인터럽트 백터
- 인터럽트 각 종류별로 몇번 라인의 인터럽트인지 나타냄
- 그 인터럽트가 들어왓을때 운영체제의 메모리 어디에 있는 인스트럭션을 실행해야하는가 처리해야 할 주소를 가지고 있다.
- 번호와 주소 쌍을 갖고있는게 인터럽트 백터입니다.(점프를 하게하는 것이 인터럽트 백터)
- 예를들어 3번라인이 셋팅되면 벡터에서 3번에 해당하는 주소(함수 위치를 알리고 있음) 해당 커널 함수에 즉, 실제 해야 할 일이 있음
cpu는 매번 프로그램카운터가 가르키고있는 곳을 실행하며, 인터럽트가 들어오면 cpu 제어권이 운영체제로 자동 넘겨짐
cpu안에 모드빗이라는 것이 0이냐 1이냐 따라 ...
0이면, 모든 기계어 집합 실행 가능
- 운영체제가 가지고있을땐 모드빗 0
- 그중에 다른 사용자 메모리를 본다던가 i/o 디바이스에 접근한다던가 이런것은 운영체제만 가능하다 (모드빗 0)
- i/o디바이스에 접근하는 모든 것은 모드빗이 0 일떄만 가능합니다.
1이면, 한정된 기계어 인스트럭션들만 실행 가능
- 1일때는 사용자 프로그램이 cpu를 가짐
- 그럴 땐 한정된 인스트럭션만 사용 가능 ( 사용자 프로그램은 100퍼 믿지 못함, 보안을 위함 )
- 자기 메모리 주소만 보고 일을 할 수 있다.
- 사용자 프로그램이 i/o작업을 해야 할 떄 운영체제에게 요청을 해야 한다
- 그럴땐 프로그램 카운터 레지스터가 운영체제 주소영역으로 점프를 해야 하는데 모드빗이 1일때 못하기 떄문에 사용자 프로그램이 운영체제에게 무엇인가를 요청하는 것을 System Call 이라고 한다.
- 또는 운영체제의 함수를 사용자 프로그램이 요청할때
시스템 콜 어찌하는지?
의도적으로 인터럽트 라인 셋팅을 한다.
그럼 cpu는 셋팅된 것을 보고 하던일을 멈추고 cpu 제어권을 운영체제에게 넘긴다.
인터럽트의 종류
디바이스 컨트롤러와 같은 하드웨어가 발생시키는 인터럽트를 하드웨어 인터럽트라고 한다.
일반적으로는 하드웨어 인터럽트를 뜻한다.
프로그램이 직접 필요에 따라 인터럽트 라인 셋팅해서 운영체제를 부르는 것을 소프트웨어 인터럽트 또는 트렙이라고 부른다.
트렙은 두종류
1. System Call
사용자 프로그램이 필요에 의해서 운영체제에게 서비스를 해달라고 요청하는 것을 시스템 콜이라고 부른다.
2. Exception
사용자 프로그램이 오류에 의해서 트렙이 발생할 수 도 있다 (ex. 0으로 나누는 연산은 허용이 안됨)
cpu에서 인스트럭션을 실행하다가 오류를 만나면 모드빗이 1인데 이상한 일을 하려고했기떄문에 인터럽트 라인이 자동으로 셋팅이 된다. 그 프로그램도 cpu가 자동으로 운영체제에게 제어권이 넘어간다.
보통은 그것은 프로그램 강제 종료가 된다.
I/O 컨트롤러들이 cpu에 인터럽트를 걸 수 도 있지만
타이머라는 하드웨어가 있는데 타이머도 인터럽트를 걸 수 있다.
운영체제가 cpu를 사용자프로그램에게 넘길때 모드빗을 1로 바꿔 넘기는데 보안적으로는 잘 막아지지만,
안놓고 계속 무한으로 쓰는 것을 도와주는 것이 타이머입니다.
한 프로그램이 독점하는 것을 방지
운영체제는 타이머 인터럽트의 도움을 받아 여러 프로그램을 번갈아 실행할 수 있다.
이화여자대학교 :: CORE Campus (ewha.ac.kr)
동기식 입출력과 비동기식 입출력
동기식 입출력 (Synchronous I/O)
✅ I/O 요청 후 입출력 작업이 완료된 후에야 CPU 제어권이 사용자 프로그램에게 넘어감 (기다림)
싱크로노스, 립싱크 시간적으로 서로 맞추는것을 싱크로노스라고한다.
구현 방법 1
- I/O가 끝날 때까지 CPU를 낭비시킴 (기다림, I/O 장치 하나만 일하고 있음)
- 매시점 하나의 I/O만 일어날 수 있음
구현방법2
- I/O 가 완료될 때까지 해당 프로그램에게서 CPU를 빼앗음 ( => cpu가 놀지 않고, i/o 장치도 동시 여럿 실행 가능 )
- I/O 처리를 기다리는 줄에 그 프로그램을 줄 세움 (요청에 대한 것이 끝나면, 컨트롤러가 인터럽트를 검)
- 다른 프로그램에게 CPU를 줌
비동기식 입출력 (Asynchronous I/O)
✅ I/O 가 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에게 즉시 넘어감
✅ 두 경우 모두 I/O의 완료는 인터럽트로 알려줌
i/o 장치에는 동시에 여럿이 접근이 가능합니다.
i/o 까지 직접가서 결과를 보고 오는것을 동기식 입출력이라고 한다.
기다리지 않고 작업이 들어가면 비동기(에이싱크로노스)하다고 이야기 한다.
아이오 작업은 오래 걸리는 작업이라 시간이 흘러야 나중에 도착한다.
- 기다려서 다음작업을 한다면, 싱크로노스
- 아이오 작업이 진행되는데 그것을 기다리지 않고 바로 cpu 제어를 얻어 다른 작업을 하는 것은 에이싱크로노스
- 끝났다고 알려주는것은 둘다 인터럽트를 통해 알린다.
DMA (Direct Memory Access)
DMA (Direct Memory Access)란?
✅ 빠른 입출력 장치(인터럽트를 번번히 건다)를 메모리에 가까운 속도로 처리하기 위해 사용
메모리를 접근할수잇는 장치가 cpu뿐 ㅡ> I/O 장치들이 cpu랑 교신을 할 때 인터럽트를 건다.
예를 들면,
- input 디바이스 요청이 오면 cpu가 해당 로컬 버퍼 내역을 memory에 카피를 해오고
- 아웃풋 디바이스 요청이 오면 메모리 내역을 로컬 버퍼에 보낸다던가 그런식으로 할 것임
그러나 I/O 장치는 워낙 다양하고 키보드같은 경우 1바이트를 cpu가 카피해오고 또 입력하면 또 인터럽트를 건것을 카피해오고... 이런식으로하면 cpu가 인터럽트를 너무 많이 당함 (오버헤드가 뒤따름 )
작은 하나하나가 cpu가 효율적으로 동작하지 못하게 하기떄문에 dma를 붙였다
✅ cpu의 중재 없이 device controller가 device의 buffer storage 의 내용을 메모리에 block 단위로 직접 전송
✅ 바이트 단위가 아니라 block 단위로 인터럽트를 발생시킴
메모리 접근을 DMA도 직접 접근 가능하도록 만들어 놨다
해당 버퍼의 특정 크기 블럭 또는 페이지의 데이타가 쌓이면 그것이 끝났다고 CPU 에 한번 인터럽트를 건다
DMA가 해당 내역을 메모리로 카피를 하고 어느 정도 블럭에 해당하는 데이타가 I/O가 끝나면
인터럽트를 한번 걸어서 아까 요청한 작업이 끝났다고 CPU에게 알린다.
이런식으로 CPU 인터럽트 빈도를 낮춰 효율성을 높힌다.
서로 다른 입출력 명령어
✅ I/O 를 수행하는 Special instruction 에 의해
우리가 cpu에 실행할 수 있는 기계어 인스트럭션에는 메모리만 접근하는 인스트럭션( = 로드 스토어) 이 있고
I/O 장치에만 접근해야하는 인스트럭션이 있다.
메모리 접근 주소 따로 I/O 디바이스 접근하는 주소가 달라서 따로하는 것이 일반적인 방식
✅ Memory Mapped I/O 에 의해
I/O 디바이스들에다가 메모리 주소를 매겨서 메모리 접근하는 인스트럭션을 통해서 I/O 를 할 수 있다
이거를 memory Mapped I/O 라고 부른다
저장장치 계층 구조
맨위의 초록영역 위에 CPU가 존재
✅ 초록영역은 cpu에서 직접 접근할 수 있는 메모리 스토리지 매체이며 이를
프라이메리(Primary) 또는 익스큐터블(Executable)이라고 한다.
(Executable은 실행 가능하다라는 뜻!)
✅ 분홍색 영역은 cpu가 직접 접근해서 처리 못하는 것을
세컨더리(Secondary)라고 부른다.
프라이메리(Primary) | 세컨더리(Secondary) |
저용량, 고가, 빠른 속도 | 대용량, 저가, 느린 속도 |
휘발성 매체 ( 전원 종료시 데이터 소멸 ) | 비휘발성 매체 ( 전원 종료시 데이터 유지 ) |
익스큐터블(Executable) CPU직접 접근 가능 | CPU 직접 접근 불가, I/O 컨트롤러에 요청해 데이터 가져옴 |
✅ 저장장치 계층 구조 특징
- speed
- cost
- volatility
위로 갈수록 ⬆
✅ 속도가 빠른 매체를 사용하고 대신에 단위 공간당 가격이 비싸다.
✅ 그래서 위일 수록 또 용량이 적다고 한다.
✅ 또 한가지 특징은 휘발성 매체냐 아니냐 / 연두색 : 휘발성 매체로 구성, 분홍색 : 비휘발성 매체로 구성이 된다.
하드디스크나 테입은 전원이 나가도 내용이 사라지지 않는 비휘발성 매체입니다.
반명에 디렘이나 캐쉬메모리로 사용되는 메모리나 이런것들은 전원이 나가면 사라지는 휘발성 매체입니다.
연두색 영역은 휘발성 매체로 구성이되고 분홍색 구역은 비휘발성 매체로 구성이 된다.
요즘은 또 발전하고 있어서 메인메모리가 비휘발성으로 가능한 것도 있지만 전통적으로는 이런 특징을 가지고 있다.
✅ Caching : copying information into faster storage system
cpu가 직접 접근하려면 바이트 단위로 접근가능한 매체여야 한다
디렘 메모리 같은 경우 바이트 단위로 주소를 매겨 가능하다. Executable 함
그에 비해 하드디스크는 바이트단위 접근이 아닌 새터 단위로 접근하기 떄문에 Executable 하지 않은 매체 입니다.
위로 갈수록 용량이 적고 비싸서 아래쪽에 있는 내용을 전부 위에 올려 놓지는 못한다
속도 차이도 있다고 햇는데 cpu가 인스트럭션을 처리하는데 있어 빠르게는 원클락당 하나씩 처리하게 되는데,
디렘은 10-100 클락 사이클까지 걸리는데 오래 걸린다.
이런 속도 차이를 완충 시키기 위해 중간에 캐쉬메모리를 두고 또 레지스터를 읽어들이는 작업을 한다.
✅ 캐쉬메모리는 메인메모리보다 용량이 작아 모든 것을 담지 못하고 당장 필요한것만 밑에 있는것들을 올려서 쓰는데 그것을 캐싱이라고 한다.
✅ 캐싱은 빠른 매체로다가 정보를 읽어들여서 쓰는것을 말한다.
✅ 보통 캐싱은 재사용을 목적으로 한다
처음은 어쩔수없이 아래부터 읽어들여야 한다
두번째는 밑에까지 가지않고 이미 위에 읽어둔 것을 바로 읽어 갈 수 있는 기법 효과
근데 용량이 위에갈수록 적어지기 떄문에 기존에 새로운 것들이 들어오면 쫒아내야 한다
어떤 것을 쫒아내야하는가는 캐싱의 중요한 이슈 뒤에서 설명해주신다고 한다.
프로그램의 실행 ( 메모리 load )
프로그램이 어찌 컴퓨터에서 실행되는지
보통 프로그램이라는 것은....
실행파일 형태로 하드디스크(파일 시스템)에 파일 형태로 저장되어 있고, 그런 실행파일을 실행시키게되면 그게 메모리로 올라가서 프로세스가 되서 실행이 됩니다.
물리적인 메모리에 바로 올라가는게 아닌 한단계를 거치게 되는데 그것이 바로 Virtual memory 입니다.
버츄얼 메모리 = 가상 메모리
버츄얼 메모리는?
✅ 각 프로그램마다 독자적으로 가지고 있는 메모리 주소 공간을 말함
이 모든게 다 물리적 공간에 가지 않음.
쪼개져서 필요한 것들은 물리적 메모리 / 그렇지 않으면 스왑 에리어
어떤 프로그램을 실행시키게 되면, 그 프로그램의 주소 공간(adress space)이 생성이 되는데
메모리 주소 공간입니다.
0번지부터 시작하는 그 프로그램만의 독자적인 공간이 생기게 됨
프로그램 a의 주소가 0번지부터 시작해 만들어지는 독자적 주소 공간
✅ 주소 공간은 code, data, stack으로 구성
- code는 cpu에서 실행할 기계어 코드를 담고
- data는 변수나 전역변수 같은 프로그램이 사용하는 자료구조를 담음
- stack은 코드가 함수구조로 되어있기때문에 함수를 호출하거나 리턴할때 데이터를 쌓았다가 꺼내는 용도로 사용하는 영역
커널(운영체제)은 부팅하고나면 메모리에 상주해서 올라가있지만,
사용자 프로그램들을 실행시키면 주소 공간이 생겼다가 프로그램 종료 시키면 사라지게 된다.
이 주소 공간을 물리적 메모리에 다 올리지 않고, 낭비하지 않기 위해
✅ 당장에 필요한 부분은 물리적 메모리(Physical memory)에 올려 놓고,
✅ 그렇지 않은 부분은 디스크(Swap area)에 내려놓는다.
프로그램 실행으로 만들어진 주소공간은 물리적인 메모리에 통쨰로 모두 올리는 것이 아니다.
매우 메모리 소모적이게 되어 당장에 필요한 부분만!
a함수를 실행하고있다면 해당하는 코드만 올리고 사용을 다하면 쫒아내듯 불필요한 낭비를 하지 않는다.
주소 공간은 머릿속에만 있는 것이고, 실제로 연속적으로 할당되는 것이 아닌
쪼개져서 어떤 부분은 물리적인 곳에 어떤곳은 Swap area 에 내려가있다.
그래서 이것을 버츄얼 메모리라고 부릅니다.
file system 과 swap area 두 하드디스크의 다른 용도
그래서 하드디스크가 file system 도 있고 Swap area도 있지만 용도가 다르다.
✅ file system
1. 전원이 나가도 내용이 유지됨
2. 비휘발성
✅ Swap area
1. 메모리 용량의 한계로 연장공간으로써 사용
2. 전원이 나가면 의미 없는 데이터임
3. 휘발성
Adress translation 주소 변환
각 프로그램마다 0번지 부터 시작하는 주소공간이 있다고 했는데,
사실 물리적 메모리도 사실 0번지부터 시작하는 주소가 존재 한다.
예를 들면 버츄얼에서 1000번진데 물리적은 3000번으로 올라가는 식으로 주소가 바뀌어야하는데
이것을 주소변환이라고 합니다
주소변환 계층은 운영체제가 아닌 하드웨어의 지원을 받아서 하는 것. (후에 메모리 관리 부분에서 배운다)
버츄얼 주소 > 물리적 주소로 바뀌는지 나중에 배움
커널 주소 공간의 내용
커널 운영체제도 사실 하나의 프로그램이라 코드 데이타 스텍 의 구성으로 주소 공간이 있다.
코드
운영체제는 무슨일을 해야 할까요?
1. 자원을 효율적으로 관리하는 일
2. 사용자에게 편리한 인터페이스 제공
3. 언제 cpu를 얻게 되는가? 각각의 인터럽트 때마다 무슨일을 처리해야하는가 커널에 함수형태로 있을 것
시스템 콜과 하드웨어가 발생시키는 인터럽트들 등...무슨 일을 해야할지
과 관련된 기능이 있을 것이다
데이터
운영체제가 사용하는 여러 자료구조들이 정의가 되어 있다.
- 운영체제는 cpu나 메모리 디스크 같은 하드웨어들을 직접 관리하고 통제 함
하드웨어를 관리하기위해서 종류마다 자료구조를 하나씩 만들어서 관리하고 있을 것이다
그런 모습을 추상적으로 그려놓은 그림
ㅡ> 육면체는 실제 하드웨어를 뜻하고/ 사각형은 그런 하드웨어를 관리하기 위한 자료구조를 의미
- 운영체제는 또 프로세스들을 관리한다
- PCB
PCB란? (프로세스 컨트롤 블럭)
시스템안에 프로그램이 하나 돌아가면, 그 프로그램을 관리하기 위한 자료구조가 운영체제 커널에 하나씩 만들어지는데 그것이 PCB라고 합니다.
현재 실행중인 프로그램들을 관리하기 떄문에 각 프로그램들이 독자적인 주소 공간을 갖고 있지만 이런것들을 관리하기 위한 자료구조가 필요하다. 그것을 PCB라고 한다. 다음 수업때 나옴
Stack 영역
운영체제도 함수구조로 코드가 짜여있어서
함수를 호출하거나 리턴할때 Stack 영역을 사용해야 한다.
그래서 커널 스텍이라는것이 있는데 운영체제의 코드는 여러 프로그램들이 요청에 따라 불러서 쓸 수 있다.
a든 b든 시스템콜을 사용해서 쓸 수 있듯
함수 호출해서 커널 스텍을 쓸 떄 어떤 사용자 프로그램이 사용하는지에 따라
즉 사용자 프로그램마다 커널 스텍을 따로 두고 있다.
사용자 프로그램이 사용하는 함수
함수(function)
사용자 정의 함수
- 자신의 직접 작성한 프로그램에서 정의한 함수
라이브러리 함수
- 자신의 프로그램에서 정의하지 않고 갖다 쓴 함수
- 자신의 프로그램의 실행 파일에 포함되어 있다
커널 함수
- 운영체제 프로그램의 함수
- 커널 함수의 호출 = 시스템 콜
- 내 프로그램엔 커널 함수 정의 X
사실 모든 프로그램이 다 함수 구조로 짜여있다.
언어에 따라서 별도로 짜여진 코드가 컴파일이 되서 기계어가 만들어지더라도 기계어 구조에서는
함수에 해당하는 정보가 어디서 어디까지인지 유지되어 있다.
내가 만든 것을 불러서 하는것을 사용자 함수라고 하고
라이브러리 함수는 기능이 유용해서 누가 만든 것을 가져다 쓰기 할때 쓰는 함수를 말한다.
사용자 정의 함수든 라이브러리 함수든 컴파일해서 실행파일을 만들게 되면,
내 실행파일 안에 이 함수들이 모두 포함되어있다 ( 내가 만들지 않아도 ㅇㅇ )
반면에 커널함수는 운영체제 안에서 정의된 함수다.
이것은 프로그램안에서 시스템 콜을 통해 가져다 쓸 수 있다
이 함수는 내 프로그램에 들어있는 함수가 아닌 커널 안에 들어있다 (내 프로그램엔 커널 함수가 정의되어 있지 않다)
사용자, 라이브러리 함수는
프로그램을 실행시키게되면 사용자 프로세스 코드 영역에 있어서 해당 내부에서 점프해서 실행되게 되지만
커널 함수로 실행하게 되면 메모리 주소를 바꾼다 쩜프를 한다는것은
물리적 인곳에서의 점프가 아닌 ! 버츄얼 메모리 즉 논리적 메모리 주소상의 점프입니다.
물리적 차원에서 보면 사용자 프로그램이 커널 영역에 접근할수없는 이유도 있다. 그래서 시스템콜을 통해 인터럽트를 통해 cpu 제어권을 넘겨서 커널 함수를 실행하게 하는 것
프로그램의 실행
a라는 프로그램이 시작이 되서 종료될 때까지의 모습
프로그램이 직접 cpu를 잡고 있으면 user mode에 있다고 한다.
프로그램이 유저 모드 안에서 자기가 정의한 사용자 정의함수를 쓸 수 있다.
그러다가 시스템 콜을 하게 되면, kernel mode 가 된다
그 프로그램의 주소공간 코드가 아닌 커널에 있는 주소공간의 코드가 실행됨
시스템 콜이 끝나게 되면 a라는 프로그램한테 cpu 제어권이 넘어오고
본인의 주소공간에 있는 코드를 실행하게 될 것
경우에 따라서 라이브러리 함수도 호출할테지만, 여전히 자신의 주소 공간에 있는 코드를 실행
그러다가 또 시스템 콜이나 인터럽트 ㅡ> a에서 커널로 제어권 ㅡ> 커널 주소공간에 있는 코드를 실행
프로그램은 태어나서 죽을때까지 유저모드 커널모드를 반복하게 될 것
'스터디 > 운영체제' 카테고리의 다른 글
운영체제 강의 1차 (운영체제란, 목적, 분류) (0) | 2023.04.28 |
---|