사실 나는 공룡책 열어본 적도 없고 하드웨어 한 우물만 파서 운영체제가 뭐하는 놈인지는 잘 몰라. 그러나 추상적인 작업을 지시하면 해석해서 알아서 해주는 아주 큰 프로그램이라고만 생각하고 있어.
운영체제도 결국은 하나의 프로그램이기 때문에 건드려서는 안되는 구역이 존재해. 예를 들어 프로그램 코드라던가 중요한 핵심 데이터라던가... 그 프로그램 안에서 수많은 프로그램이 돌아가는건데 이건 프로세스의 개념이야. 만약 이 프로세스가 운영체제의 역린을 건드리게 되면 어떻게 될까? 인터럽트 핸들러 주소를 자신의 프로그램으로 설정하고 종료하는거지. 이게 도스 시절에서는 드라이버를 구현하는 하나의 방법이기도 했어. 근데 잘못된 인터럽트 핸들러 주소를 설정하거나 변조시키면 시스템에 문제가 발생하겠지. 보안을 위해서 이러한 행동을 못하게 막아야 했어. 그래서 메모리 보호 장치라는 외부 장치가 나온거야. 이론은 간단해. 전체 메모리를 여러개의 덩어리로 나누고 권한이 없는 덩어리에 접근하는 시도가 있으면 인터럽트를 발생시키지. 그러나 이 방법도 문제가 좀 많아. 프로그래밍을 할때 항상 실제 메모리의 주소가 어떻게 될지 염두에 두고 작성해야 하고 접근만 차단할 뿐이지 실제 주소는 알아낼 수 있어서 이로 인한 보안 취약점이 발생할 수 있어(이 때문에 현대적인 운영체제는 커널이 메모리에 올라갈때 항상 같은 위치에 올라가지 않아.)(만약 멜트다운 보안 취약점을 이용한다면 실제 커널 주소를 알 수 있으니 0번지부터 메모리 끝까지 뭐든지 다 알아낼 수 있어.) 또 다시 해결방법은 가상 메모리라는 기술이야. 플랫 메모리 모델에 가장 적합한 기술이지. 모든 프로그램은 실제 메모리의 주소를 생각하면서 프로그래밍해야할 필요성이 없어졌고 프로세스가 접근하는 메모리가 실제 메모리 주소로 바로 변환되지 않기 때문에 커널 주소를 함부로 알아낼 수 없어. 메모리 보호 장치만 있었을때 같은 프로그램을 10개 실행했고 프로세스가 10개가 생성되었다면 이들 프로세스의 코드 주소, 데이터 영역 주소는 각자 다를거야. 그러나 가상 메모리라는 기술을 이용하여 프로그램마다 독립적인 메모리 공간을 제공하기 때문에 프로세스들은 메모리 주소의 0번지도 사용할 수 있어. (실제로 사용하진 않지만 가능성은 있다는 뜻.) 그러나 프로세스 각자에게 독립된 공간을 준다는게 메모리 전부를 준다는 건 아니기 때문에 여전히 가상 메모리 안에서도 접근이 불가능한 주소가 있어. 이건 라이브러리 호출로 메모리를 할당받거나 해야한다. 어차피 32비트 프로세서에서 각 프로세스마다 2 GiB씩 가상 메모리를 쥐어준다면 4 GiB 벽에 도달하니 전부 쓰지 못하니까.
아무튼 메모리 보호라는 개념과 가상 메모리는 다른 것이야. 그러나 메모리 보호가 있어야만 가상 메모리가 존재할 수 있지.
우리는 메모리 관리 장치가 무슨일을 하는지 신경쓰면서 프로그래밍 할 필요는 없어. 세그먼테이션이나 페이징 같은 이론은 하드웨어 개발자가 아니라면 알지 않아도 되. 그러나 확실한건 부정한 메모리 접근이 일어나지 않도록 항상 자신의 논리가 올바른지 포인터 관리를 제대로 하고 있는지 점검하는게 더 중요할거야.
좀 특이할지도 모르겠지만 8비트 프로세서를 사용하던 시절에는 운영체제 영역의 주소를 전부 분석해서 어떤 주소는 어떤 목적으로 사용되는지 다 알 수 있기 때문에 굳이 시스템 호출을 사용하는것보다 직접 메모리 조작을 하는게 더 빨랐어. 근데 그건 64킬로바이트도 안되는 시스템에서나 가능한 이야기지 지금은 바이트만 수십억 단위고 비트 단위로 생각하면 8배나 많기 때문에 TempleOS도 그런 짓은 못할거야 아마.
댓글 0