운영체제와 정보기술의 원리(3)

Chapter 2 System structure & program execution

운영체제에 앞서서 컴퓨터 하드웨어에 관한 전반적인 지식을 배울 강의. 복습하는 기분으로 .

2019-02-25 9 23 46

컴퓨터 시스템. 크게 CPU와 메모리로 구성된 컴퓨터와 I/O device 들로 구성.

메모리란 것. cpu의 작업 공간. cpu는 매 클럭 사이클마다 기계어(instruction)를 하나씩 읽어서 일을 한다.

I/O device: ex) 하드디스크, 키보드, 프린터, 모니터 등

하드디스크는 i/o device라고도 볼 수 있어. 인풋 역할도 하고 아웃풋 역할도 한다. 각각의 I/o device들은 그 디바이스를 전담하는 작은 cpu 같은 것들이 붙어있다. 그걸 device controller라고 부른다.

디스크에서 헤드가 어떻게 움직이는지, 그 내부를 통제하는 건 cpu의 역할이 아니라 디스크컨트롤러가 그런 작업을 한다. 키보드 컨트롤러도 마찬가지다.

main cpu의 작업 공간인 메인 메모리가 있듯이, 이러한 device controller들도 그들의 작업 공간이 필요하다. 그게 local buffer다. cpu와 i/o device는 처리하는 속도차이가 많이 난다.

cpu에 비해서 디스크만해도 100만배 정도가 느리다. 디스크를 cpu가 직접 관장하지 않고 device controller가 맡아하고 있고, cpu는 매 클럭마다 인스트럭션을 하나씩 읽어서 실행하는 작업만 한다. 평생 메모리에서 인스트럭션을 읽어서 실행. 그게 cpu의 운명.

cpu 안에는 메모리 보다 더 빠르면서 정보를 저장할 수 있는 작은 공간이 있어. 그게 레지스터야.

cpu안에 mode bit이라고 있는데, 지금 cpu에서 실행되고 있는 것이 운영체제인지, 사용자 프로그램인지를 구별해준다.

interrupt line이란 것이 cpu에 붙어 있는데, 이건 왜 ? cpu는 메모리에 있는 instruction만 실행. 인스트럭션 하나가 실행되고 나면 다음번에 실행할 기계어의 주소값이 증가하고, 그러면 다음 사이클에서는 그다음 인스트럭션을 실행하고 그런 역할만 실행한다. 키보드에서 어떤 입력이 들어왔다던가, 디스크에서 뭘 읽어와야 한다던가, 그러한 요청을 했는데, 그게 완료되었는지 그런 것들을 전달하기 위해서 interrupt line이라 한다. 그래서 cpu는 메모리하고만 일한다.

cpu를 프로그램 A가 실행하고 있다고 하면. 이 프로그램이 cpu에서 인스트럭션을 실행하다가. 경우에 따라서는 키보드 입력(스캔에프)을 받을 수도 있고, 디스크에서 file을 읽어와서 실행하는 경우도 있고

cpu는 i/o device를 직접 접근하지 않고 메모리를 접근하는 인스트럭션만 실행하게 되어있다. 그러다가 디스크에다 무엇을 읽어오라는 요청을 어떻게 보내냐. 인스트럭션을 실행하다가 프로그램 A가 디스크에서 뭘 읽어와야 한다, 한다면 cpu가 직접 디스크로 접근하는게 아니라. 디스크컨트롤러한테 특정 데이터를 읽어오라고 일을 시킨다. (일을 시키는 instruction이 있다.) 디스크는 요청한 데이터를 읽어오게 되고. (컨트롤러의 지시를 받아서) 읽어오는 작업은 굉장히 오래걸린다. 디스크는 시킨 일을 하면서 읽어서 자신의 로컬 버퍼에 집어넣게 된다. 그러는 동안에 굉장히 빠른 cpu가 놀고 있으면 낭비가 된다. 그래서 보통은 프로그램이 쭉 메모리 접근만 하면서 실행이 되다가 i/o를 하게 되면 i/o에 대한 일은 i/o 컨트롤러한테 시키고 다시 메모리에 접근해서 일을 한다.

그런데 디스크에서 뭘 읽어오라고 했으면, 읽어온 결과물을 보고 그 다음 인스트럭션을 실행하는게 프로그램의 구조다. 또는 프로그램이 스캔 에프를 통해서 키보드에서 뭘 읽어오라 했으면, 읽은 값이 뭐냐에 따라서 무슨 일을 할지가 결정이 된다. 키보드에서 뭘 읽어오는 그런 인스트럭션을 만나게 되면 , 키보드 컨트롤러 한테 얘기를 한다. 사용자가 키보드를 눌러서 인풋이 들어오면 그 때 나에게 알려달라하고, 키보드에서 입력이 들어오는지 안들어오는지는 개의치 않고 오래걸리는 작업이기에 본인이 할 수 있는 일을 계속 실행하는거다. 그리고 cpu는 다른 할일을 한다.

즉 cpu는 굉장히 빠른 일꾼. 그래서 프로그램 여러개가 동시에 실행될 때, cpu는 짧은 시간 간격으로 왔다갔다 가면서 처리하기 때문에 사용자 입장에서 보면 굉장히 인터렉티브하게, 빠르게 응답해주는 것처럼 보인다.

문제 : 무한루프 같은 프로그램. 계속 cpu만 쓰는. 그럼 종료되지도 않고. 계속 쓰이는 문제 그렇게 되면 cpu가 다른 프로그램에게 넘어가지 못해서 time sharing을 구현 할 수 가 없어. 그래서 타이머라는 하드웨어가 있어. 타이머라는 하드웨어의 역할은 특정 프로그램이 cpu를 독점하는 것을 막는 거야.

컴퓨터 켜 -> 운영체제가 cpu가 가지고 있다가 프로그램들을 키면 그 cpu를 넘겨주고 타이머에 값을 세팅한 후에 넘어간다. 할당된 시간. 수 십 밀리세컨드 시간. 세팅해서 cpu를 넘겨준다. cpu는 자기 인스트럭션 넘겨주고, 세팅된 시간이 되면 타이머가 cpu한테 인터럽트를 건다. cpu는 하나의 인스트럭션이 끝나면 인터럽트 라인 체크. 그 작업 반복. 타이머가 인터럽트를 걸어 왔으면 cpu는 하던일을 멈추고 제어권이 운영체제로부터 사용자 프로그램으로 자연스럽게 넘어간다. 한번 넘어가면 뺏을 수는 없지. 뺏을려면 이 친구도 본인이 cpu를 가지고 있어야 하는데, cpu를 넘겨준 다음에는 운영체제가 아무리 똑똑해도 뺏을 방법이 없다. 그래서 추가적인 타이머란 하드웨어를 걸어서 cpu 제어권이 자동적으로 사용자 프로그램에서부터 운영체제로 넘어간다.

i/o를 해야하면 프로그램이 자진해서 cpu를 넘겨준다. 사용자 프로그램은 본인이 i/o 장치에 접근할 수 없다. 이는 운영체제를 통해서만 가능하도록 해놓음. 보안상의 이유 때문. i/o 작업을 해야한다면 운영체제에게 cpu를 넘겨주고, 운영체제가 i/o 컨트롤러에게 시키는거다. 운영체제는 요청한 프로그램에게 cpu를 넘기는게 아니라. 다른 프로그램에게 넘겨주게된다. 프로그램에서 요청한 작업은 언제 다시 cpu를 얻게 되냐? 키보드에서 입력이 들어와야지 처리를 하니까. i/o컨트롤러가 요청한 작업이 끝나서 키보드 입력된 데이터가 자신의 버퍼에 들어왔다. 그러면 키보드 컨트롤러가 cpu한테 인터럽트를 건다. 그러면 제어권이 운영체제에게 넘어가게 된다. 운영체제가 인터럽트가 왜 들어왔냐 살펴봤더니 키보드 입력이 들어온거야. 그러면 입력된 키보드 값을 아까 키보드 입력 요청한 프로그램의 메모리 공간에 카피를 해주고, 그 다음에 방금전에 누군가가 cpu를 쓰다가 입터럽트를 당했으니까. 일단 다시 그 친구한테 cpu를 준다. 한정된 시간이 남아잇다고 하면, 그 친구가 cpu를 더 쓰게하고. 할당된 시간이 끝나면. 키보드 입력이 들어와서 준비가 완료된 프로그램에게 cpu를 주게된다.

정리

프로그램 실행이 되다가. 디스크에서 무언가 읽어오라는 요청 발생. 디스크 안 원판이 있고. 헤드가 이동하면서 데이터가 있는 위치에서 뭔가 읽는 작업을 하겟지. 그걸 cpu가 -> 디스크 컨트롤러에게 시켜. 디스크 컨트롤러가 해당 위치에서 데이터를 읽고 있고. 그 동안에 cpu는 또 다른 일이 있는 프로그램에게 작업 넘어가고, 디스크 컨트롤러가 읽어오는 작업이 끝나면, cpu에게 인터럽트를 걸어서 작업을 알려줌. 인터럽트가 들어왔기 때문에, cpu는 운영체제에게 자동으로 넘어간다. cpu는 인터럽트를 봤더니, 디스크 작업이 끝났구나. 그러면 디스크 local buffer에 있는 내용을 , 읽어오라던 친구, 메모리 영역으로 카피를 해주고. 보통은 그 친구에게 바로 cpu를 주는게 아니라. 아직 cpu를 쓰고 있는 프로그램의 할당 시간이 끝날 때 까지 넘겨주는 방식을 동작을 하게 된다.

mode bit

사용자 프로그램의 잘못된 수행으로 다른 프로그램 및 운영체제에 피해가 가지 않도록 하기 위한 보호 장치. 0이면 운영체제가 cpu에서 수행중 -> 커널모드, 시스템 모드 (무슨 일이든 다 가능하게 정의되어 있음. 메모리 접근, i/o device 접근 가능)

mode bit이 1이면 -> 사용자 프로그램이 cpu를 가지고 있을 때, 그럴 때는 제한된 instruction 만 실행될 수 있게끔 되어있다. 보안상의 목적.

i/o장치로 접근. 다른 프로그램의 메모리 공간, 이런 시도를 하면 모드bit이 1인걸 보고 안되게 하드웨어적으로 구현. 인터럽트게 들어오게 되면 cpu 제어권이 운영체제에게 넘어가면서 mode bit이 0으로 바뀌게 된다.

사용자 프로그램의 나쁜짓 보안 관리.

timer

특정 프로그램의 cpu 독점을 막음

device controller

i/o 장치를 전담하는 일종의 작은 cpu. 제어 정보를 저장하는 컨트롤 레지스터, status 레지스터 있고 , local buffer를 가진다.

데이터 자체는 로컬 버퍼에 넣고, 파일에 저장하라는 명령은 제어레지스터를 통해서 (cpu가 i/o컨트롤러에게 전달) 뭐 화면에 출력하라는 지시도 마찬가지로 제어 레지스터를 통해서 전달.

메모리를 전담하는 컨트롤러도 있어. 메모리라는 것도 디바이스니까.

메모리를 원칙적으로 cpu만 접근할 수 있게 해놓은 거야. 메인 메모리는 cpu만 접근하고 i/o device들은 자기 자신들의 로컬 버퍼가 존재하니까. 버퍼에 받아서 일을 하게 되고 버퍼에 쌓이게 되면 cpu가 그 내용을 읽어서 자신의 작업 메모리에 복사를 하고. 그러니 사실 cpu는 메모리와 local buffer에 접근 가능하고 작은 cpu들 (device 컨트롤러들은 자기 버퍼에만 접근 가능하고)

그렇게 하다 보니까 cpu가 너무 인터럽트를 많이 당한다. 그래서 DMA controller라는 메모리를 하나 더 두고 있다. 직접 메모리에 접근할 수 있는 컨트롤러. 원래는 메모리에 접근할 수 있는 장치는 cpu 뿐이었는데, DMA 컨트롤러를 두게 되면 cpu도 접근할 수 있고 DMA도 접근할 수 있게. 둘이 동시에 접근하면 문제가 생기니까. memory controller는 이를 조율하는 교통정리 역할을 한다.

DMA controller-> i/o 장치가 너무많이 인터럽트를 거니까. 역할: 중간에 작업이 들어왔을 때, cpu가 로컬버퍼에 카피하게 하는게 너무 정보량이 크니까. local buffer 작업 다 끝나면 메모리로 복사하는 작업을 다 해주고, 다 끝났으면 cpu에 인터럽트 한번 걸어서 한번에 처리.

device driver / device controller

device driver -> 장치구동기. os 코드 중 장치별 처리 루틴 -> 소프트웨어 device controller -> 장치제어기. 각 장치를 통제하는 일종의 작은 cpu -> 하드웨어

결국 cpu의 숙명은 본인이 이번에 실행해야할 인스트럭션의 메모리 주소를, 레지스터 중에서 프로그램 카운터라는 pc라는 레지스터가 다음번에 어디에 있는 인스트럭션을 실행할지 주소를 가지고 있거든. 그것만 실행하는 운명 i/o장치 접근 운명 -> 디바이스 드라이버를 통해서 명령. 디바이스 드라이버가 실제로 뭔가 헤드를 움직여서 하는 그런 코드가 아니라 (디스크에서) 그런 코드는 디스크 컨트롤러가 직접 일하고. cpu는 메모리의 지시를 받아서 일을 한다. 디바이스 드라이버도 메뉴얼이 있다. 그건 디스크 안에 펌웨어 라고 해서 이 친구를 동작하기 위해서 뭘 해야하는지. 적혀있다. 디바이스 드라이버는 cpu가 실행하는데 수행할 코드를 담고 있다.

메뉴얼. 몇번지의 일을 하라고 적혀있다. cpu는 그냥 그걸 하는거야. cpu에 대한 전체적인 통제를 운영체제가 해야한다.

I/o 입출력의 수행 . 모든 입출경 명령은 특권 명령

사용자 프로그램은 어떻게 I/o 하는가?

운영체제엑 부탁한다. 이를 시스템 콜이라고 한다. 사용자 프로그램이 운영체제의 커널, 함수를 호출하는 걸 시스템 콜이라고 부르고. 일반 함수호출과는 다르다.

(첫시간에 한학기 다 설명)

재 사용자 프로그램을 실행하다보면 함수 호출을 하는 부분이 있다. 그래서 처음에 프로그램이 cpu에서 메인 함수를 실행할 때, 메인함수에 해당하는 instruction을 실행할거야. 그 함수가 다른 함수를 호출하면 jump를 한다. 순차적으로 실행이 되다가 instruction의 메모리 위치로 점프. 반복문이면 다시 올라오고 이런 식으로 실행이 된다. 내 프로그램 안에서 함수호출하는건 이 안에서 메모리 주소를 바꾸는 건데. 운영체제의 함수를 호출하는 건. 그건 시스템 콜. 그냥 메모리 주소를 바꿔서 되는게 아니라. 어떤 식? -> 디바이스 컨트롤러들이 시스템에 인터럽트를 걸 수 있다고 했잖아. 그런 식으로 인터럽트를 걸어서 시스템 콜을 실행한다.

즉 내가 내 프로그램을 실행하다 i/o를 해야한다 -> 직접 메모리로 점프 안돼. i/o를 하기 위해 운영체제로 접근 mode bit 1인데 ? 어떻게 가능. 이 안에서만 가능한데 i/o를 하기 위해 운영체제에 해당하는 주소로 넘어가야한다. 그럼 어떻게 ?

interrupt

프로그램이 직접 interrupt line을 세팅하는 인스트럭션을 실행한다. 이 프로그램이 cpu를 가지고 있으면 인스트럭션 하나가 실행되고 나면 인터럽트 들어온게 있는지 체크를 한다. 타이머가 인터럽트를 걸거나 i/o 컨트롤러가 인터럽트를 거는게 아니라 프로그램이 운영체제에게 무언가를 요청하기 위해서 소프트웨어적으로 인터럽트를 걸 수 있다. cpu는 이 프로그램의 다음 인스트럭션을 실행하는게 아니라 인터럽트가 들어왔으므로 모드빗이 0으로 바뀌고 cpu제어권이 운영체제로 넘어간다. 운영체제가 cpu를 가지고 있으므로 디스크 컨트롤러한테 읽어오라고 부탁을 할 수 있게 되는거다. 인터럽트는 하드웨어 일꾼들이 cpu한테 뭔가 정보 교신을 하기 위해 걸어줄 수도 있고 사용자 프로그램이 돌아가다가 내가 직접 처리못하고 운영체제에다가 대신해달라고 요청하는 상황에서도 interrupt line을 세팅을 해서 os한테 cpu가 넘어갈 수 있다 후자는 소프트웨어 인터럽트, 다른 말로 trap. 소프트웨어가 인터럽트를 거는, 일반적으로 인터럽트는 하드웨어 -> i/o, 타이머 같은 것들. 보통은 인터럽트라고 하면 하드웨어. 소프트웨어는 trap이라는 말을 쓴다.

인터럽트를 걸어서 시스템 콜을 해서 사용자 프로그램이 os에게 요청을 했는데 아무거나 다 들어주면 안돼. 올바른 요청인지 확인해보고 올바른 요청인 경우에 i/o 요청을 부탁하게 된다. i/o 컨트롤러에게. 요청한 일을 한다. 그게 시간이 오래걸리므로 cpu는 다른 프로그램에게 넘어가고. 그 i/o가 끝나면 하드웨어 인터럽트가 걸린다.

현대의 운영체제는 인터럽트에 의해 구동됨

  1. 사용자 프로그램이 i/o를 요청할 때 발생하는 인터럽트 -> 소프트웨어 인터럽트. 너 아이오 해라 os가 일을 시킴. 시킨일이 다 끝나면 하드웨어 인터럽트가 걸림 cpu에게 알려줌.

i/o 요청은 소프트웨어 다 끝나면 하드웨어 인터럽트를 통해서 알려주고. 두가지 다 필요하다.

cpu를 특정 프로그램이 독점하는 것을 막기 위해서 타이머 인터럽트라는 걸 사용하고 있고 그 다음에 요청한 아이오가 다 끝났다는 것을 알려주기 위해서, 또는 키보드에 입력이 들어왔다는 걸 알려주기 위해서 그런 걸 전달하는 건 아이오 컨트롤러가 인터럽트를 걸어서 알려주게 되는 거고.

시스템 콜은 사용자 프로그램이 i/o나 운영체제한테 뭔가 부탁할 때. 그럴 때 부탁하는 방법이 시스템콜.

인터럽트 벡터 : 해당 인터럽트의 처리 루틴 주소를 가지고 있음 인터럽트 처리 루틴 : 해당 인터럽트를 처리하는 커널 함수 (인터럽트 핸들러)



참고자료

운영 체제와 정보 기술의 원리 - 반효경 지음

kocw 반효경 교수님 14년도 운영체제 강의

0%