구조의 이해에 앞서 반드시 집고 넘어가야할 이론이나
용어들이 있습니다.
저번에는 아주 기본적 사항만 다뤘고 여기서는 좀더 발전하여
시그널과 예외처리 그리고 인터럽트에 대해 알아보겠습니다.
[인터럽트와 예외처리 그리고 DMA]
입출력이나 그외의 장치에서 발생되는 인터럽트의 처리과정을 살펴
보겠습니다..
프로그램에서 하드디스크의 자료를 입출력 하는것을 한번 예로 들어보면
우선 프로그램이 화일을 읽기위해 read()시스템 콜을 불렀다고 합시다
이 read()에서는 디스크 드라이버를 구동 시키게되고 그 드라이버에게
할일을 지시 시키고서는 되돌아 오게 되는데 이렇게 해서 데이타를
디스크에서 읽어올동안 많은 시간이 낭비되므로 그동안에 다른일을
하기위해 해당 프로세스를 일시중단 시켜 잠들게하고(sleep)
다른프로세스를 수행시키게하여 cpu는 다른일을 계속 수행을 하게됩니다.
그동안 디스크 드라이버는 다시 디스크 컨트롤러 장치에게 데이타를
읽어 올 것을 지시하고 디스크 컨트롤러는 하드디스크에서 직접적으로
데이타를 읽어와서 컨트롤러 내부의 임시 기억장소에 저장 시켜놓습니다.
다 읽어왔으면 cpu에게 이 컨트롤러가 인터럽트를 걸어버립니다.
인터럽트 핸들러(처리부)
그럼 cpu는 현재수행 프로세스를 중지 시키고서는 미리 내정된 메모리의
주소로 그 제어를 옮기게 되는데 바로 요부분이 커널의 인터럽트 핸들러
부분인것입니다.
이제 이 인터럽트 핸들러는 지금 무슨 인터럽트가 발생되었는지
판단하여 이를 기다리고 있던(아까 읽기위해 read()를 호출한 프로세스)
프로세스를 깨우게 됩니다(wake up)..
(여기서 깨운다는 말은 실행 중지상태 서 다시 cpu를 할당 받아
실행된다는 의미입니다)
이렇게 다시 실행을 재개한 프로세스는 이제 컨트롤러의 임시기억 장소에
있는 데이타를 자신의 메모리 영역으로 옮겨오게 되어 read鄕ㅐ?
다 마치게 되는거죠..
다른것들도 위와 똑같은 인터럽트 처리과정을 수행하게 됩니다.
DMA 처리
위의 인터럽트처리 과정의 마지막 부분에서 보면 컨트롤러 장치의 임시기억
장소(다수의 레지스터들)로 부터 메인 메모리로 데이타를 옮기기 위한
과정은 어떻습니까.. cpu가 이일을 하는거죠..
다른일을 충분히 할수있는 시간에 쓸데없이 이일을 cpu가 맡아서 한다는건
아주 비효율적이죠.. 그래서 바로 이일을 전담하기위해 DMA라는 방식을
쓰는겁니다.
보드에보면 DMA컨트롤러가 있어서 이놈이 각종장치의 임시기억장소로
부터 메인메모리로 데이타를 옮겨놓는 역할을 합니다.. 그럼으로해서
cpu는 그동안 다른일을 할수있는거죠. 인터럽트보다는 한단계 발전된 형태
입니다.
실제에 있어서 보면 DMA컨트롤러가 cpu의 외부버스를 장악하여 쓸수
있게끔 cpu에게 먼저 나지금 무슨 버스를 쓰고자하니 cpu님이 양보해
달라는 요청을 하고 이를 수신한 cpu는 상황을 보고 그래 너가 써라라고
해주면 비로서 DMA컨트롤러가 그버스를 장악하여 위와같이 외부장치로 부텀
메인 메모리로 데이타를 옮길수있는겁니다.
예외 처리란?
위와 같은 프로그램내에서 필요에의해 발생된 인터럽트와는 달리
예상치못한 상황(0으로나누는것,정전사태,불법메모리 엑세스등)
과 같은 비동기적 사건에서 발생되는 것들을 따로 묶어서 예외상태라
합니다. 물론 그동작은 인터럽트와 똑같죠. 그러나 하드웨어적인
인터럽트와의 차이점은 인터럽트 대신에 신호를 사용한다는 겁니다.
아래에서 이에 관한 시그널 처리를 알아 보겠습니다.
[유닉스의 시그널 처리]
시그널(signal)이란 말그대로 신호 즉 커널이 프로세스에게 어떠한
신호를 보내거나 한프로세스가 다른 프로세스에게도 신호를 보내는
등의 일을 말합니다.
그럼 왜 신호가 필요 할까요..?
프로그램은 때때로 다음과 같은 예상치 못한 사건들에 대해 대처를
해야 하는데 이들은 보는것 처럼 언제 일어 날지 모르는 비동기적
사건이므로 이를 처리하기 방편으로 바로 시그널(신호)를 사용합니다
이런 사건들이 발생 했을때 커널이 해당 프로세스에게 야 너 지금
이런 일이 일어났으니 대처 하라고 알려주는거죠.. 이 알려준다는게
바로 신호를 보낸다는 겁니다..
* 부동 소수점 에러
* 정전
* 알람클록
* 자식프로세스의 죽음
* 사용자의 종료 요구(control C)
* 사용자의 일시 중지 요구(control Z)
처리 과정 : 이런한 사건이 일어나면 커널은 이를 일으킨 프로세스에게
신호를 보내고 그프로세스를 일시정지 시킨후 신호처리기를
구동시킨다.
이렇게 해서 그신호처리후 다시 그프로세스를 처리하게 됩니다.
이렇게 미리 정의된 커널의 신호처리기를 수행할수도 있는거고
또 프로그램내에서 따로 정의해서 처리시킬수도 있습니다.
또한 프로세스들끼리도 서로 신호를 보내기위한 방법으로
kill()이라는 시스템콜을 사용하게됩니다..
참고로 왜 kill() 이라는 이름이냐 하면 초창기 유닉스에서
프로세스간의 신호는 프로세스를 죽이는 신호밖에 없었기
때문에 kill이라는 이름아 붙은 겁니다. 지금은 여러가지용도의
신호에 사용되죠.
신호의 처리의 한가지 예 :
지금 전면(포그라운드)에서 실행중인 프로세스를
강제로 종료시키기 위해 우리는 Control_C를 누르게 됩니다.
터미널 드라이버가 이 control_c를 인식하면 현재 전면 작업중에있는
모든 프로세스들에게 SIGINT라는 시그널을 전달하게 됩니다. 이를
받은 프로세스는 작업을 중단하고 커널의 신호 처리기가 수행되어
SIGINT에 적합한 처리를 하여 프로세스의 작업을 강제로 종료 시켜
버리는 겁니다.
인터럽트 처리과정과 똑같다고 보시면됩니다.
또 위에서 단순히 신호를 주고 받는다는 추상적인 말을 썼는데
실제에 있어서는 커널에는 모든프로세스의 관리를 위한 테이블을
마련해 두고있는데 여기에 보면 각 신호의 수신을 위한 비트열
들이 있게됩니다. 이 비트열들중에 하나를 세트시키거나 하여 신호를
알리는 것입니다. 다음올라갈글인 프로세스 구조를 다루게 될것인데
거기 보시면 완전히 이해 가실겁니다.