최근 프로그래밍에 대한 입문을 되돌아보면, 의도적으로 메모리 주소를 무작위로 읽고 쓰는 C++ 프로그램을 작성했던 기억이 납니다. 나는 무슨 일이 일어날지 보고 싶어서 이렇게 했습니다.
놀랍게도 내 Windows 98 PC에서는 내 프로그램에 매우 이상한 부작용이 있었습니다. 때로는 운영 체제 설정을 전환하거나 그래픽 결함을 생성합니다. 일반적으로 아무 작업도 수행하지 않거나 전체 시스템에 충돌이 발생합니다.
나중에 이것이 Windows 98이 사용자 프로세스가 액세스할 수 있는 대상을 제한하지 않았기 때문이라는 것을 알게 되었습니다. 다른 프로세스는 물론 운영 체제에서도 사용되는 RAM을 읽고 쓸 수 있습니다.
나는 이것이 Windows NT의 출현으로 바뀌었다는 것을 이해합니다(비록 수정하는 데 시간이 좀 걸렸다고 생각합니다). 이제 Windows에서는 귀하에게 속하지 않은 프로세스에 대해 RAM을 볼 수 없습니다.
나중에 Linux 시스템에서 내 프로그램을 실행했지만 그렇게 많은 흥미로운 결과를 얻지 못한 것을 어렴풋이 기억합니다. 내가 올바르게 이해했다면 이는 적어도 부분적으로 사용자 공간과 커널 공간이 분리되어 있기 때문입니다.
그래서 내 질문은 다음과 같습니다.
리눅스가 사용자 공간과 커널 공간을 분리하지 않던 시절이 있었나요? 즉, 내 악성 프로그램이 Linux 시스템에 비슷한 피해를 입힌 적이 있습니까?
답변1
Linux는 항상 사용자 공간이 사용하는 메모리에 직접 액세스하는 것을 방지하여 프로세스가 서로의 메모리에 직접 액세스하지 못하도록 보호해 왔습니다. 프로그램은 커널에 의해 매핑된 메모리에 액세스할 수 있는 가상 주소 공간을 통해서만 메모리에 액세스할 수 있습니다. 할당된 메모리 외부의 메모리에 액세스하면 분할 오류가 발생합니다. (프로그램은 악명 높은 /dev/mem
및 를 포함한 시스템 호출 및 드라이버를 통해 커널에 액세스할 수 있습니다 /dev/kmem
. 또한 서로 메모리를 공유할 수도 있습니다.)
MMU가 Unix/Linux 커널 내부에 있습니까? 아니면 자체 메모리가 있는 하드웨어 장치에만 있습니까?오늘날 Linux에서 커널/사용자 분리가 처리되는 방식을 설명합니다(이전 버전의 Linux는 이를 다르게 처리했습니다. 참조).Linux 메모리 관리 개요그리고80386 메모리 관리더 알아보기).
예를 들어 일부 Linux 관련 프로젝트에서는 이러한 분리를 없앱니다.내장 가능한 Linux 커널 하위 집합8086 CPU와 호환되는 Linux의 하위 집합이므로 하드웨어 강제 보호를 제공하지 않습니다.µClinux메모리 관리 장치가 없는 임베디드 시스템에 대한 지원을 제공합니다. 핵심 "구성 요소"는 이제 메인라인 커널의 일부이지만 "PC" 아키텍처에서는 이 구성이 불가능합니다.
답변2
리눅스가 사용자 공간과 커널 공간을 분리하지 않던 시절이 있었나요?
"Linux", "사용자 공간", "커널 공간"이라는 용어를 어떻게 정의하느냐에 따라 달라집니다.
Linus Torvalds가 원래 Linux를 어떻게 만들었는지 기억하시나요? Linus는 약간의 돈을 절약하여 Intel 80386 CPU가 장착된 (당시 최첨단) PC를 구입했습니다. 그는 80386이 어떻게 작동하는지 이해하고 싶었고 이를 수행하는 가장 좋은 방법은 80386 어셈블리에서 일부 하위 수준 하드웨어 코드를 작성하는 것이라고 생각했습니다. 동시에 그는 대학에 로그인할 때 사용했던 Minix에서 실행되는 터미널 에뮬레이터의 성능에 만족하지 못했습니다.
그래서 그는 80386 어셈블리를 사용하여 직접 시작할 수 있는 터미널 에뮬레이터를 작성하기로 결정했습니다. 이를 위해 그는 부트로더, 키보드 드라이버, (문자) 디스플레이 드라이버, 직렬 드라이버 및 대학 연결에 사용되는 모든 프로토콜에 대한 드라이버를 작성해야 합니다.
곧 그는 자신도 대학에서 파일을 다운로드하고 싶다는 것을 알게 되었고, 그래서 일부 파일 전송 프로토콜(아마도 ZMODEM이지만 단순화를 위해 XMODEM을 선택했을 수도 있음)과 하드 드라이브, 파티션 테이블 파서 및 파일을 구현해야 했습니다. Minix 파일 시스템 드라이버용 시스템입니다. 그는 또한 터미널 에뮬레이터가 일부 장기 실행 작업(예: 파일 다운로드)을 수행하는 동안 계속 작업하기를 원했기 때문에 멀티스레딩을 구현했습니다.
이 시점에서 그는 운영 체제의 일부 중요한 부분을 이미 구현했다는 것을 깨달았으므로 터미널 에뮬레이터를 운영 체제로 바꾸는 것이 또 다른 흥미로운 프로젝트가 될 것이라고 생각했습니다.
그 후 어느 시점에서 그는 실수로 잘못된 명령을 입력하여 Minix 파티션을 백업으로 덮어썼습니다. 이제 그는 Minix를 다시 설치하거나 운영 체제를 종료하고 사용하는 선택에 직면했습니다.
그의 운영 체제가 간단한 프로그램을 실행할 수 있게 되자 그는 이를 대학의 FTP 서버에 업로드하기로 결정하고 이름을 Freax로 지정했습니다(그는 자신의 이름을 따서 명명하는 것이 가식적이고 오만하다고 생각했습니다). 그러나 FTP 서버의 시스템 관리자는 이름이 마음에 들지 않아 파일 이름을 Linux로 바꾸기로 결정했습니다. Linux가 더 좋다고 생각했기 때문입니다.
얼마 후 Linus는 유명한 연설에서 Linux를 처음으로 공개적으로 언급했습니다. Linux는 80386과 너무 밀접하게 연관되어 있어 다른 어떤 것으로도 포팅될 수 없으며 Linux는 결코 거대해지거나 전문적이지 않을 것이라고 예측했습니다.
이제 문제는 이 여정의 어느 시점에서 "Linux"가 "Linux"가 되고, 이 여정의 어느 시점에서 Linux가 "커널"이 되는지입니다. 따라서 사용자 공간과 커널 공간의 분리에 대해 이야기하는 것이 타당합니다. ?
처음에 말했듯이, 이 용어를 어떻게 정의하느냐에 따라 달라집니다.
즉, 내 악성 프로그램이 Linux 시스템에 비슷한 피해를 입힌 적이 있습니까?
나중에 운영 체제가 되고 "Linux"라고 불리는 소프트웨어가 아무런 보호도 없고, "커널"이라고 부를 수 있을 만큼 서비스가 복잡하고, 충분히 독립적이었던 소프트웨어가 개발되던 때가 분명히 있었습니다. 이러한 하위 시스템을 "프로그램"이라고 부를 수 있습니다. 예를 들어, "실제" Unix 시스템에서 터미널 에뮬레이터와 파일 전송은 일반적으로 두 개의 별도 프로그램이며 직렬 포트, 하드 드라이브, 화면, 키보드 및 파일 시스템에 대한 액세스를 포함하는 이 두 프로그램 간의 조정자는 커널 .
그런데 이 소프트웨어가 "Linux"인가요? 결정은 여러분에게 맡기겠습니다.
답변3
예, Linux에서는 메모리 보호를 위해 항상 MMU가 필요했습니다. 많은 사람들이 이것을 MMU가 없는 소형 임베디드 시스템으로 포팅하고 있지만 더 이상 전체 메모리 보호 기능이 없으므로 프로세스는 거의 모든 것을 읽고 쓸 수 있습니다.