운영 체제를 실행하지 않고 운영 체제를 어떻게 실행합니까?


167

지금 정말 궁금합니다. 저는 파이썬 프로그래머이고이 질문은 저를 놀라게했습니다 : 당신은 OS를 작성합니다. 어떻게 운영합니까? 그것은 어떻게 든 실행되어야하며 그 방법은 다른 OS 내에 있습니까?

OS에 있지 않고 어떻게 응용 프로그램을 실행할 수 있습니까? OS가없는 경우 컴퓨터가 C를 실행하고 이러한 명령을 화면에 실행하도록하려면 어떻게합니까?

UNIX 커널과 관련이 있습니까? 그렇다면 유닉스 커널 또는 일반적인 커널이란 무엇입니까?

OS가 그보다 더 복잡하다고 확신하지만 어떻게 작동합니까?


14
나는 그것이 BIOS의 목적이라고 확신합니다-더 큰 OS의 실행을 부트 스트랩하는 정말 작은 OS입니다.
sevenseacat

64
OS는 편리 하지만 컴퓨터에서 프로그램을 실행하기 위해 필요하지는 않습니다.
Andres F.

10
OS없이 비 OS 소프트웨어를 작성하는 것도 완벽하게 가능합니다. 많은 Forth 통역사는 전통적으로 OS없이 운영되었습니다 (또는 OS라고 말할 수 있습니다). 그렇게 어렵지는 않습니다. C를 알고 있다면 학습 연습으로 이러한 프로그램 (작은 게임)을 작성하는 것이 좋습니다.
Max

44
이러한 혼란은 오늘날 우리가 사용하는 훌륭하고 안전하며 고도로 추상화 된 컴퓨팅 시스템의 비용 중 하나입니다. 사람들은 매우 훌륭하고 유능한 프로그래머 가 될 수 있으며 컴퓨터 작동 방식에 대한 기본 사항조차 알 수 없습니다. 얼마나 가고 싶니? 물리량이 매우 낮지 만 여전히 높으면 첫 번째 마이크로 프로세서는 어떻게 프로그래밍 되었습니까?를 참조하십시오 . Electronics.SE.
dmckee

2
프로그래밍은 현재 OS 개념의 발명 이전에 수행되었습니다. 분명히 그 수준에서 무언가가 OS를 시작합니다. OS가 부트 스트랩됩니다. 대부분 컴퓨터 운영 체제 과정이 필요하기 때문에 어느 시점에서 CS 4 년 프로그램에서 언급됩니다.
Rig

답변:


263

부팅 프로세스를 거치는 많은 웹 사이트 (예 : 컴퓨터 부팅 방법 )가 있습니다. 간단히 말해서, 최종적으로 OS 프로세스를 시작할 수있을 때까지 시스템을 조금씩 구축하는 다단계 프로세스입니다.

CPU를 시작하고 실행하려고하는 마더 보드의 펌웨어로 시작합니다. 그런 다음 다른 하드웨어를 시작하고 실행하는 미니 운영 체제와 같은 BIOS를로드합니다. 이 작업이 완료되면 부팅 장치 (디스크, CD 등)를 찾은 다음 MBR (마스터 부팅 레코드)을 찾아 메모리에로드하여 실행합니다. 이 작은 코드는 운영 체제를 초기화하고 시작하는 방법을 이해하는 것입니다 (또는 더 복잡한 다른 부트 로더). 이 시점에서 커널과 같은 것들이로드되고 실행되기 시작합니다.

그것이 작동한다는 것은 정말 놀랍습니다!


108
마지막 문장 +1
CVn

39
"부팅"이라는 이유가 있습니다. 이 용어는 "부트 스트랩에 의해 스스로를 끌어 당기는"과 같이 "부트 스트랩 핑 (bootstrapping)"의 약자입니다.
KeithS

5
누군가 부트 스트랩 코드를 키 또는 토글해야 할 때가있었습니다. 때로는 ROM의 프로그램의 첫 번째 명령으로 간단히 넘어갔습니다. 다른 경우에는 장치에서 읽고 코드를 읽은 데이터의 첫 번째 프로그램 명령으로 이동하는 것이 코드였습니다. 상황이 훨씬 간단 해졌습니다.
BillThor


15
@BillThor : "훨씬 더 간단하다"는 것은 물론 "훨씬 더 복잡하다"는 의미입니다. 사용하기더 간단합니다 .
Raphael Schweikert

173

A "베어 메탈"운영 체제가 실행되지 않습니다 내에서 아무것도. 물리적 시스템에서 전체 명령 세트를 실행하고 가상 메모리 지원 하드웨어를 제어하는 ​​명령을 포함하여 모든 물리적 메모리, 모든 장치 레지스터 및 모든 권한있는 명령에 액세스 할 수 있습니다.

(운영 체제가 가상 머신에서 실행중인 경우 위와 동일한 상황에 있다고 생각할 수 있습니다 . 차이점은 특정 항목이 가상 시스템을 실행하는 레벨과 같은 하이퍼 바이저에 의해 에뮬레이트되거나 다른 방식으로 처리된다는 것입니다. .)

어쨌든, OS는 (예를 들어) C로 구현 될 수 있지만, 사용 가능한 모든 일반 C 라이브러리를 가지고 있지는 않습니다. 특히, 일반적인 'stdio'라이브러리가 없습니다. 오히려 디스크 블록을 읽고 쓸 수있는 디스크 장치 드라이버를 구현할 것입니다. 디스크 블록 계층 위에 파일 시스템을 구현하고 그 위에 사용자 응용 프로그램의 런타임 라이브러리가 파일을 만들고 읽고 쓰는 등의 시스템 호출을 구현합니다.

OS에 있지 않고 어떻게 응용 프로그램을 실행할 수 있습니까?

I / O 하드웨어 등과 직접 상호 작용하는 방법을 알고있는 특별한 종류의 응용 프로그램 (예 : 운영 체제)이어야합니다.

OS가없는 경우 컴퓨터가 C를 실행하고 이러한 명령을 화면에 실행하도록하려면 어떻게합니까?

당신은하지 않습니다.

응용 프로그램 (C로 작성된 인수를 위해)은 원시 코드 이미지를 제공하기 위해 다른 컴퓨터에서 컴파일되고 링크됩니다. 그런 다음 BIOS에서 찾을 수있는 위치에 이미지가 하드 드라이브에 기록됩니다. BIOS는 이미지를 메모리에로드하고 명령을 실행하여 응용 프로그램의 진입 점으로 이동합니다.

완전한 운영 체제가 아니라면 응용 프로그램에 "일반적으로 C 실행 및 명령 실행"이 없습니다. 이 경우 운영 체제는 필요한 모든 인프라를 구현해야합니다. 마법이 없습니다. 많은 코드입니다.

Bill의 답변 은 전원이 꺼진 시스템에서 일반 운영 체제가 실행중인 시스템으로 이동하는 프로세스 인 부트 스트랩 을 포함합니다. 그러나 BIOS가 작업을 완료하면 일반적으로 주 운영 체제에 하드웨어를 완전히 제어하고 다음 시스템이 다시 시작될 때까지 더 이상 역할을 수행하지 않습니다. 메인 OS는 확실히 기존의 의미에서 BIOS 내에서 실행되고 있지 않습니다.

UNIX 커널과 관련이 있습니까? 그렇다면 유닉스 커널 또는 일반적인 커널이란 무엇입니까?

그렇습니다.

UNIX 커널은 UNIX 운영 체제의 핵심입니다. 위에서 설명한 모든 "베어 메탈"작업을 수행하는 것은 UNIX의 일부입니다.

"커널"의 개념은 시스템 소프트웨어를 핵심 장치 (실제 장치 액세스, 모든 메모리 등 필요)와 비 핵심 요소로 분리하려고한다는 것입니다. 커널은 핵심 요소로 구성됩니다.

실제로 커널 / 코어와 비 커널 / 비 코어의 차이점은 그보다 더 복잡합니다. 그리고 실제로 커널에 속하는 것과 그렇지 않은 것에 대해 많은 논쟁이있었습니다. (예를 들어 마이크로 커널을 찾으십시오.)


6
경이적인 답변. 가능하면 더 많은 투표를하겠습니다.
weberc2

7
여기에 많은 답변이 있으므로 지금까지 아무도 언급하지 않았으므로 이것을 주석으로 추가 할 것입니다. OS의 주요 기능 중 하나는 여러 응용 프로그램이 사용자의 관점에서 "동시"실행되도록 허용하는 것입니다. 프로세스를 예약하고 프로세스가 서로의 동작을 변경하지 않도록 보호하는 기능은 일반적으로 펌웨어 또는 BIOS가 아닌 OS에서만 제공되는 기능입니다.
Sean Barbeau

2
The idea of a "kernel" is that you try to separate the system software into core stuff핵심어 / 핵을 의미 kernel하는 독일어 라는 용어를 기억하면 쉽게 기억할 수 Kern있습니다.
deed02392

1
이 답변은 C가 아닌 실행되고 컴파일 된 이진 코드로 언급되어 있기 때문에이 답변을 좋아하십시오.
Travis Pessetto

3
"그로부터 멀어지면 PC 사용자는 덜 영리해진다." -덜 똑똑하지 않고 ... 또한 PC 사용자 수가 증가했다고 말할 수도 있습니다.
Stephen C

62

처음에는 CPU에 전원이 없었습니다.

그리고 남자는 "전원을 공급하자"고 말했고, CPU는 메모리의 주어진 주소에서 읽기 시작했고 거기에 있던 명령을 실행하기 시작했습니다. 그런 다음 전원이 끝날 때까지 다음을 계속하십시오.

이것은 부팅이었다. 주요 소프트웨어가 있던 환경에 액세스하기 위해 다른 소프트웨어를로드하여로드하는 것이 었습니다.

마지막으로, 친숙한 화면에서 로그온하도록 초대했습니다.


58
이 답변은 christianity.stackexchange.com으로 이동해야합니다
Coomie

6
"주어진 주소"는 어디에서 왔습니까? 찰스 다윈을 플레이해서 죄송합니다.
Midhat

7
@Midhat-CPU가 가져 오는 첫 번째 주소는 그 안에 고정되어 있습니다. 보통 0입니다.
mouviciel

17
... 그리고 7 일째에, 남자는 그의 게임으로 쉬었습니다
Canadian Luke

9
@mouviciel 메모리의 ADRESS은 0x7C00어떤을위한 x86첫번째 호환 아키텍처와 것은 멋진 대답하지만 ... 일반적으로 부팅 가능한 어떤 장치가 선호의 첫 번째 섹터를로드하는 BIOS에 의해 작성되어야한다 : -7
토비아스 Kienzler

29

늦어서 죄송하지만, 다음과 같이 설명하겠습니다 :

  • 마더 보드에 전원이 공급됩니다.

  • 타이밍 회로는 전기적 특성에 따라 필요한 경우 시작되고 안정화됩니다. 일부 최신 장치는 실제로 매우 제한된 마이크로 프로세서 또는 시퀀서를 사용할 수 있습니다.

    "필요한 경우 타이밍 회로가 시작되고 안정화됩니다"와 같은 많은 것들이 더 이상 하드웨어에서 실제로 발생하지 않습니다. 엄청난 양의 작업은 실제로 매우 제한된 서브 프로세서 / 시퀀서에서 실행되는 매우 전문화 된 소프트웨어입니다.

    - jkerian 에서 10 월 25 일 5시 20분

  • CPU와 RAM에 전원이 공급됩니다.

  • CPU는 내부 배선을 기준으로 BIOS에서 데이터를로드합니다. 일부 컴퓨터에서는 BIOS가 RAM에 미러링 된 다음 거기서 실행될 수 있지만 IIRC는 드 rare니다.

    켜져 있으면 x86 호환 CPU가 주소 공간의 주소 0xFFFFFFF0에서 시작합니다.

    -Micheal Steil, Xbox 보안 시스템에서 Microsoft가 저지른 17 가지 실수 ( archive )

  • BIOS는 마더 보드에서 디스크 및 기타 하드웨어 IO에 사용하는 하드웨어 포트 및 주소를 호출하고 디스크를 스핀 업하고 나머지 RAM을 작동시킵니다.

  • BIOS 코드 (하드웨어에 저장된 CMOS 설정을 통해)는 하위 수준 IDE 또는 SATA 명령을 사용하여 CMOS에서 지정한 순서대로 또는 메뉴로 사용자 재정 의하여 각 디스크의 부팅 섹터를 읽습니다.

  • 부팅 섹터가있는 첫 번째 디스크는 부팅 섹터를 실행합니다. 이 부트 섹터는 디스크에서 더 많은 데이터를로드하고 더 큰 NTLDR이후 단계를 로드하는 지침이있는 Assembly입니다 GRUB.

  • 마지막으로, OS 머신 코드는 부트 로더에 의해 대체 또는 오프셋 위치에서 부트 섹터를로드하는 체인로드를 통해 직접 또는 간접적으로 실행됩니다.

그런 다음, 친숙한 커널 패닉, 질식 된 펭귄 또는 머리 충돌로 인해 디스크가 멈 춥니 다. =) 대안 시나리오에서 커널은 프로세스 테이블, 메모리 내 구조를 설정하고 디스크를 마운트하고 드라이버, 모듈 및 GUI 또는 서비스 세트 (서버에있는 경우)를 마운트합니다. 그런 다음 헤더를 읽을 때 프로그램이 실행되고 어셈블리가 메모리로 가져와 적절히 매핑됩니다.


2
"타이밍 회로는 필요한 경우 시작하고 안정화"와 같은 많은 것들이 더 이상 하드웨어에서 실제로 발생하지 않는다는 점에 주목해야합니다. 엄청난 양의 작업은 실제로 매우 제한된 서브 프로세서 / 시퀀서에서 실행되는 매우 전문화 된 소프트웨어입니다. -친절한 동네 펌웨어 엔지니어
jkerian

@jkerian 내 게시물에 의견을 인용 했습니까?
ζ--

전혀 아냐.
jkerian

BIOS는 운영 체제 가 아닙니다 . BIOS는 기본 입 / 출력 시스템에 대한 속기, 그것은 이다 BIOS가하는 일. 프로그래머가 제조업체에서 제공 한 드라이버와 함께 저수준 리소스를 사용할 수 있습니다. OS가 보호 (32 비트) 또는 긴 (64 비트) 모드로 들어가면 BIOS는 더 이상 사용할 수 없으며 OS는 기본적으로 BIOS가 "낮은"수준에서 제공 한 기능을 대체하는 자체 드라이버를 사용합니다. Linux 및 Windows와 같은 최신 운영 체제는 사용 가능한 RAM 섹션을 감지하고 필요한 드라이버를로드 할 수있는 자체 고급 로더를로드 할 때만 BIOS를 사용합니다.
Hannes Karppila

1
@HannesKarppila 업데이트; 이것은 현재 약 4 살이며이 사이트에서 더 이상 활동하지 않습니다.
ζ--

15

좋은 답변이 많이 있지만 이것을 추가하고 싶었습니다. Python 배경에서 왔다고 언급했습니다. 파이썬은 해석되지 않은 (혹은 "일반적으로 CPython 사용 사례에서는"통역 된 "언어) 언어입니다. 이것은 다른 소프트웨어 (파이썬 인터프리터)가 소스를보고 어떤 식 으로든 실행하고 있음을 의미합니다. 이 모델은 훌륭한 모델이며 실제 하드웨어에서 추상화 된 고급 언어를 사용할 수 있습니다. 단점은 항상이 인터프리터 소프트웨어가 먼저 필요하다는 것입니다.

이러한 인터프리터 소프트웨어는 일반적으로 기계 코드 (예 : C 또는 C ++)로 컴파일되는 언어로 작성됩니다. 머신 코드는 CPU가 처리 할 수있는 것입니다. CPU가 할 수있는 것은 메모리에서 일부 바이트를 읽고 바이트 값에 따라 특정 작업을 시작하는 것입니다. 따라서 1 바이트 시퀀스는 메모리에서 레지스터로 일부 데이터를로드하는 명령이고, 다른 시퀀스는 2 개의 값을 추가하기위한 시퀀스입니다. 다른 시퀀스는 레지스터에서 주 메모리로 값을 다시 저장하고 곧 (레지스터는 특수 메모리 영역입니다. 가장 잘 작동 할 수있는 CPU의 경우), 이러한 명령의 대부분은 해당 수준에서 상당히 낮습니다. 이러한 기계 코드 명령어는 사람이 읽을 수있는 어셈블러 코드입니다. 이 머신 코드는 기본적으로 Windows 또는 Linux / Unix 바이너리의 .exe 또는 .com 파일에 저장되는 것입니다.

이제 컴퓨터가 시동되면 멍청하지만 배선이 있지만 기계 코드 지침을 읽습니다. PC에서 이것은 일반적으로 (현재) BIOS를 포함하는 메인 보드의 EEPROM 칩입니다 (기본 입력 출력 시스템).이 시스템은 많은 것을 할 수 없으며 일부 하드웨어 등에 쉽게 액세스 할 수 있으며 주요 작업을 수행 할 수 있습니다. 부팅하고 처음 몇 바이트 (일명 마스터 부트 레코드, MBR)를 메모리에 복사 한 다음 CPU에 "여기, 프로그램이 있습니다"라고 말하면 CPU는 해당 바이트를 기계 코드로 처리하여 실행합니다. 일반적으로 이것은 일부 매개 변수를 사용하여 커널을로드 한 다음 해당 커널에 제어권을 넘겨주는 모든 운영 체제 로더입니다. 그런 다음 모든 드라이버에 모든 하드웨어에 액세스하고 일부 데스크톱 또는 쉘 프로그램을로드하고 사용자가 로그인하고 시스템을 사용하십시오.


6
"인터 필"? 나는 그 용어를 전에 들어 본 적이 없다.
Bryan Oakley

3
이 용어는 5 년 정도 전에 사용 된 것과는 별개의 컴파일 단계를 갖는 "현대적인"인터프리터를 설명하기 위해 많이 사용되었습니다. 이 용어는 어디 살아 있다면 어떤 생각이 ;-)
요하네스

1
"해석"? 나는 그 용어를 전에 들어 본 적이 없다.
Cole Johnson

12

"OS에 있지 않고 어떻게 응용 프로그램을 실행할 수 있습니까?" 쉬운 대답은 "OS는 응용 프로그램이 아닙니다"입니다. 응용 프로그램과 동일한 도구를 사용하여 OS를 만들 수 있고 동일한 원료로 만들 수 있지만 동일한 것은 아닙니다. OS는 응용 프로그램과 동일한 규칙으로 재생할 필요가 없습니다.

OTOH, 실제 하드웨어 및 펌웨어는 OS "응용 프로그램"이 실행되는 "OS"로 생각할 수 있습니다. 하드웨어는 매우 간단한 OS입니다. 머신 코드로 작성된 명령어를 실행하는 방법을 알고 있으며 시작할 때 첫 번째 명령어에 대해 매우 구체적인 메모리 주소를 찾아야한다는 것을 알고 있습니다. 따라서 시작한 다음 바로 첫 번째 명령을 실행 한 다음 두 번째 명령을 실행합니다.

따라서 OS는 알려진 위치에 존재하며 하드웨어와 직접 상호 작용할 수있는 머신 코드입니다.


1
+1 이것이 가장 좋은 답변이라고 생각합니다. 추상화 측면에서 나는 당신이 올바른 수준에서 그것을 못 박고 있다고 생각합니다.
Preet Sangha

6

귀하의 질문에 대한 답변은 네이티브 (CPU) 코드의 모양과 CPU에 의해 어떻게 해석되는지에 대한 지식이 필요합니다.

일반적으로 전체 컴파일 프로세스는 C, Pascal 또는 Python으로 작성한 내용 (pypy를 사용하여) 및 C #을 CPU가 이해하는 것으로 변환하는 것, 즉 "[memory address]에 무언가 저장", "레지스터 eax에 저장된 숫자 추가" ebx ","call function foo ","eax와 10 비교 ". 하나씩 실행되는 명령은 코드로 수행하려는 작업을 수행합니다.

이제 이것에 대해 생각해보십시오.이 네이티브 코드를 실행하기 위해 실제로 OS가 필요하지 않습니다! 이 코드를 메모리에로드하고 CPU에 해당 코드가 있고 실행되도록 지시하기 만하면됩니다. 하지만 너무 걱정하지 마십시오. 그것은 BIOS가 걱정해야 할 일입니다-CPU가 시작된 직후, 물리적 주소 0x7C00에서 코드 (하나 및 하나의 섹터 만)를로드합니다. 그런 다음 CPU는이 한 섹터 (512B)의 코드를 실행하기 시작합니다. 그리고 당신은 당신이 상상하는 무엇이든 할 수 있습니다! 물론 OS의 지원이 없습니다. 운영 체제이기 때문입니다. 시원 해요? 표준 라이브러리, 부스트, 파이썬, 프로그램, 드라이버가 없습니다! 모든 것을 직접 작성해야합니다.

그리고 어떻게 하드웨어와 통신합니까? 글쎄, 당신은 두 가지 선택이 있습니다 :

  1. "실제 모드"-1MB의 메모리 만있는 CPU 실행 모드, CPU 확장, 메모리 보호, 멀티 태스킹과 같은 고급 CPU 기능은 없습니다. 16 비트 실행 코드, 고대 주소 지정 모드 ... 그러나 간단한 화면 출력, 키보드 지원, 디스크 I / O 및 전원 관리를 포함하여 BIOS에서 제공하는 일부 루틴이 있습니다. 한마디로, MS-DOS와 16 비트 CPU 시대로 돌아 왔습니다.
  2. CPU의 모든 기능, 설치 한 모든 메모리 등이 "보호 모드"로 전환됩니다. 그러나 보호 모드에서는 완전히 혼자이며 모든 것을 직접 수행해야합니다 (그리고 "in"및 "out"명령을 사용하여 I / O 포트에 데이터를 입력 및 출력하고 인터럽트를 사용하여 하드웨어와 통신해야합니다. /영형). Windows 95와 첫 번째 Linux 가이 옵션을 선택한 이후로 모든 OS를 말해야합니까?

이제 커널이 무엇인지 묻습니다. 곧 커널은 보지 못하고 직접 경험하지 못하는 모든 것입니다. 키보드부터 PC 내부의 거의 모든 하드웨어에 이르기까지 모든 것을 드라이버와 함께 관리합니다. 그래픽 쉘 또는 터미널을 통해 통신합니다. 또는 운 좋게도 OS를 지원하여 코드 내부의 기능에 의해 실행됩니다.

이해를 돕기 위해 하나의 조언을 해줄 수 있습니다. 자신의 OS를 작성해보십시오. 화면에 "Hello world"라고 쓰더라도 말입니다.


3

시스템에 매우 의존적 인 운영 체제의 작동 방식에는 몇 가지 차이점이 있습니다. 유용하려면 시스템이 "주소 X에서 실행 시작"과 같이 시작시 예측 가능한 동작이 있어야합니다. 비 휘발성 저장 장치 (예 : 플래시 메모리)가 프로그램 공간에 매핑 된 시스템의 경우 프로세서의 프로그램 공간 내 올바른 위치에 시작 코드를두기 때문에 매우 쉽습니다. 이것은 마이크로 컨트롤러에 매우 일반적입니다. 일부 시스템은 시작하기 전에 다른 위치에서 시작 프로그램을 검색해야합니다. 이러한 시스템에는 하드 와이어 (또는 거의 하드 와이어) 작업이 있습니다. 다른 칩에서 i2c를 통해 시작 코드를 검색하는 일부 프로세서가 있습니다.

x86 프로세서 제품군을 사용하는 시스템은 일반적으로 진화 및 이전 버전과의 호환성 문제로 인해 상당히 복잡한 다단계 부팅 프로세스를 사용합니다. 시스템은 마더 보드의 일부 비 휘발성 메모리에있는 일부 펌웨어 (BIOS-기본 입력 / 출력 시스템 또는 이와 유사한)를 실행합니다. 때때로이 펌웨어의 일부 또는 전부가 RAM으로 복사 (이동)되어 더 빠르게 실행됩니다. 이 코드는 어떤 하드웨어가 있고 부팅에 사용할 수 있는지에 대한 지식으로 작성되었습니다.

시작 펌웨어는 일반적으로 시스템에 어떤 하드웨어가 있는지에 대한 가정으로 작성됩니다. 몇 년 전에 286 시스템에서 I / O 주소 X에 플로피 드라이브 컨트롤러가 있고 특정 명령 세트 (및 섹터 0의 코드)가 주어진 경우 섹터 0을 특정 메모리 위치에로드한다고 가정했을 것입니다. 더 많은 코드를로드하기 위해 BIOS의 자체 기능을 사용하는 방법을 알고 있으며 결국 OS가되기에 충분한 코드가로드됩니다. 마이크로 컨트롤러에는 부팅 프로세스를 계속하기 전에 X 시간 동안 명령을 기다려야하는 특정 설정으로 작동하는 직렬 포트가 있다고 가정 할 수 있습니다.

특정 시스템의 정확한 시작 프로세스는 시스템마다 다르지만 공통점이 있다는 것을 아는 것만 큼 중요하지 않습니다. I / O를 수행해야 할 때 시작 (부트 스트래핑) 코드 내에서 인터럽트에 의존하지 않고 I / O 장치가 폴링됩니다. 인터럽트가 복잡하고 스택 RAM (아직 완전히 설정되지 않았을 수 있음)을 사용하기 때문에 유일한 작업 일 때 다른 작업을 차단할 필요가 없습니다.

OS 커널이 처음로드되면 (커널은 대부분의 OS에서 주요 부분 임) 처음에는 펌웨어와 매우 유사하게 작동합니다. 하드웨어에 대한 지식을 가지고 프로그래밍하거나 발견하고, RAM을 스택 공간으로 설정하고, 다양한 테스트를 수행하고, 다양한 데이터 구조를 설정하고, 파일 시스템을 발견하고 마운트 한 다음 아마도 더 많은 프로그램을 시작해야합니다 작성하는 데 사용되는 프로그램 (현재 존재하는 OS에 의존하는 프로그램)과 같습니다.

OS 코드는 일반적으로 C와 어셈블리를 혼합하여 작성됩니다. OS 커널의 첫 번째 코드는 아마도 항상 어셈블리 상태이며 스택을 설정하는 것과 같은 작업을 수행합니다. C 코드는 C 코드를 사용하고 C 함수를 호출합니다. OS에서 수행해야하는 일부 작업 (예 : 컨텍스트 전환 / 스왑 스택)이 C에서 표현할 수 없기 때문에 다른 수작업으로 작성된 어셈블리도 있습니다. 대부분의 C 프로그램이 사용하는 표준 라이브러리에 의존하지 않고 특수한 플래그가 있다고 기대하지 않도록 특수 플래그를 C 컴파일러에 전달해야합니다.int main(int argc, char *argv[])프로그램에서. 또한 대부분의 응용 프로그램 프로그래머가 절대 사용하지 않는 특수 링커 옵션을 사용해야합니다. 이로 인해 커널 프로그램이 특정 주소에로드 될 것으로 기대하거나 변수가 C 코드로 선언되지 않았더라도 특정 위치에 외부 변수가있는 것처럼 보이도록 설정할 수 있습니다 (메모리 매핑 된 I / O 또는 다른 특수 메모리 위치).

전체 작업은 처음에는 마술처럼 보이지만, 그 부분을 살펴보고 그 일부를 이해하면 마술은 구현하기 위해 훨씬 더 많은 계획과 시스템 지식이 필요한 일련의 프로그램이됩니다. 그러나 디버깅에는 마법이 필요합니다.


3

운영 체제의 작동 방식을 이해하려면 요청시 단순히 응용 프로그램에 서비스를 제공하는 응용 프로그램과 CPU의 하드웨어 기능을 사용하여 응용 프로그램이 원하지 않는 일을 수행하지 못하게하는 두 가지 범주로 나누는 것이 도움이 될 수 있습니다. MS-DOS는 이전 스타일이었습니다. 3.0 이후의 모든 Windows 버전은 후자의 스타일이었습니다 (최소한 8086보다 강력한 것을 실행할 때).

PC-DOS 또는 MS-DOS를 실행하는 원래 IBM PC는 이전 스타일의 "OS"의 예입니다. 응용 프로그램이 화면에 문자를 표시하려면 몇 가지 방법이 있었을 것입니다. MS-DOS에 "표준 출력"으로 보내도록 요청하는 루틴을 호출 할 수 있습니다. 그렇게하면, MS-DOS는 출력이 경로 재 지정되었는지 여부를 점검하고 그렇지 않은 경우 ROM에 저장된 루틴 (기본 IBM 입 / 출력 시스템이라고하는 루틴 콜렉션에서)을 호출합니다. 커서 위치 및 커서 이동 ( "텔레 타입 작성"). 그런 다음 BIOS 루틴은 0xB800 : 0에서 0xB800 : 3999 범위의 한 쌍의 바이트를 저장합니다. Color Graphics Adapter의 하드웨어는 해당 범위 내의 바이트 쌍을 반복적으로 가져옵니다. 각 쌍의 첫 번째 바이트를 사용하여 문자 모양을 선택하고 두 번째 바이트를 사용하여 전경색과 배경색을 선택합니다. 바이트는 읽을 수있는 텍스트 표시를 생성하는 순서로 빨강, 녹색 및 파랑 신호로 페치 및 처리됩니다.

IBM PC의 프로그램은 DOS "표준 출력"루틴을 사용하거나 BIOS "쓰기 텔레타이프"루틴을 사용하거나 디스플레이 메모리에 직접 저장하여 텍스트를 표시 할 수 있습니다. DOS 루틴을 사용하는 것보다 문자 그대로 수백 배나 빠를 수 있기 때문에 많은 텍스트를 표시해야하는 많은 프로그램이 후자의 접근 방식을 빠르게 선택했습니다. DOS와 BIOS 루틴이 매우 비효율적이기 때문은 아닙니다. 디스플레이가 비워지지 않으면 특정 시간에만 쓸 수 있습니다. 문자를 출력하는 BIOS 루틴은 언제든지 호출 할 수 있도록 설계되었습니다. 따라서 각 요청은 적절한 시간 동안 쓰기 작업을 수행하기 위해 새로 대기해야했습니다. 반대로, 필요한 작업을 알고있는 응용 프로그램 코드는 디스플레이를 작성할 수있는 기회를 중심으로 구성 될 수 있습니다.

여기서 중요한 점은 DOS와 BIOS가 텍스트를 디스플레이에 출력하는 수단을 제공했지만 이러한 기능에 대해 특별히 "마법적인"것은 없다는 것입니다. 디스플레이에 텍스트를 쓰려고하는 응용 프로그램은 적어도 디스플레이 하드웨어가 응용 프로그램이 예상 한 방식으로 작동 한 경우 (누군가 CGA와 유사하지만 문자 메모리를 가진 흑백 디스플레이 어댑터를 설치 한 경우) 효과적으로 수행 할 수 있습니다. 0xB000 : 0000-0xB000 : 3999)에 있으면 BIOS가 자동으로 문자를 출력합니다. MDA 또는 CGA와 함께 작동하도록 프로그래밍 된 응용 프로그램도 가능하지만 CGA 용으로 만 프로그래밍 된 응용 프로그램은 MDA에서 전혀 쓸모가 없습니다.)

최신 시스템에서는 상황이 약간 다릅니다. 프로세서에는 다양한 "권한"모드가 있습니다. 코드는 원하는 모든 것을 할 수있는 가장 권한있는 모드에서 시작합니다. 그런 다음 선택된 범위의 메모리 또는 I / O 기능 만 사용할 수있는 제한된 모드로 전환 할 수 있습니다. 코드는 제한 모드에서 다시 권한 모드로 직접 전환 할 수 없지만 프로세서가 권한 모드 진입 점을 정의했으며, 제한된 모드 코드는 프로세서가 권한 모드에서 해당 진입 점 중 하나에서 코드 실행을 시작하도록 요청할 수 있습니다. 또한 제한 모드에서는 금지되는 여러 작업과 관련된 권한 모드 진입 점이 있습니다. 예를 들어, 누군가 자신의 화면이있는 여러 MS-DOS 응용 프로그램을 동시에 실행하려고한다고 가정합니다. 응용 프로그램이 0xB800 : 0의 디스플레이 컨트롤러에 직접 쓸 수 있다면 한 응용 프로그램이 다른 응용 프로그램의 화면을 덮어 쓰는 것을 막을 방법이 없습니다. 반면에 OS는 응용 프로그램을 제한 모드로 실행하고 디스플레이 메모리에 대한 액세스를 트랩 할 수 있습니다. "백그라운드"에 있어야하는 응용 프로그램이 0xB800 : 160을 쓰려고한다는 것을 발견 한 경우 백그라운드 응용 프로그램 화면 버퍼로 설정 한 일부 메모리에 데이터를 저장할 수 있습니다. 해당 응용 프로그램을 나중에 포 그라운드로 전환하면 버퍼를 실제 화면으로 복사 할 수 있습니다. OS는 응용 프로그램을 제한 모드로 실행하고 디스플레이 메모리에 대한 액세스를 트랩 할 수 있습니다. "백그라운드"에 있어야하는 응용 프로그램이 0xB800 : 160을 쓰려고한다는 것을 발견 한 경우 백그라운드 응용 프로그램 화면 버퍼로 설정 한 일부 메모리에 데이터를 저장할 수 있습니다. 해당 응용 프로그램을 나중에 포 그라운드로 전환하면 버퍼를 실제 화면으로 복사 할 수 있습니다. OS는 응용 프로그램을 제한 모드로 실행하고 디스플레이 메모리에 대한 액세스를 트랩 할 수 있습니다. "백그라운드"에 있어야하는 응용 프로그램이 0xB800 : 160을 쓰려고한다는 것을 발견 한 경우 백그라운드 응용 프로그램 화면 버퍼로 설정 한 일부 메모리에 데이터를 저장할 수 있습니다. 해당 응용 프로그램을 나중에 포 그라운드로 전환하면 버퍼를 실제 화면으로 복사 할 수 있습니다.

주의해야 할 주요 사항은 (1) 텍스트 표시와 같은 다양한 표준 서비스를 수행하기위한 표준 루틴 세트를 갖는 것이 편리하지만 "권한 모드"에서 실행중인 응용 프로그램이 수행 할 수없는 작업은 수행하지 않는 것입니다. 설치된 하드웨어를 처리하도록 올바르게 프로그래밍 된 경우 (2) 오늘날 운영되는 대부분의 응용 프로그램이 운영 체제에서 이러한 I / O를 직접 수행하지 못하게되지만 권한 모드로 시작하는 프로그램은 원하는 모든 작업을 수행하고 제한 모드에 필요한 규칙을 설정할 수 있습니다 프로그램들.


2

Stephen C.가 말했듯이 운영 체제를 시작하는 것뿐만 아니라 운영 체제, 하드웨어 및 소프트웨어와 상호 작용하는 방식에 관한 것입니다.

그의 대답 에 덧붙여서 "The Computing Systems의 요소"를 보길 원할 것 입니다. 이 책은 컴퓨터, 운영 체제 및 컴파일러의 상호 작용 방식을 설명하는 서적 및 도구입니다. 이것의 독특한 점은 실제 환경에 필요한 많은 세부 사항을 무시하고 시뮬레이션 된 환경에서 자신의 운영 체제를 매우 신속하게 개발할 수있는 도구를 제공 하여 개념을 파악할 수 있다는 것 입니다. 나무 대신 숲을 볼 수있게 해주는 훌륭한 일입니다.

운영 체제가 하드웨어와 상호 작용하는 방법에 대한 자세한 내용을 보려면 Minix 를 확인하십시오 .


1

OS를 작성하십시오. 그것은 어떻게 든 실행되어야하며 그 방법은 다른 OS 내에 있습니까?

애플리케이션이 OS 내에서 실행 중입니다. 이 운영 체제는 파일 열기 및 바이트 쓰기와 같은 응용 프로그램에 서비스를 제공합니다. 이러한 서비스는 일반적으로 시스템 호출을 통해 제공됩니다.

운영 체제가 하드웨어 내에서 실행 중입니다. 하드웨어는 직렬 포트의 전송 속도 설정 및 바이트 쓰기와 같은 운영 체제에 서비스를 제공합니다. 이러한 서비스는 일반적으로 메모리 매핑 레지스터 또는 I / O 포트를 통해 제공됩니다.


이것이 어떻게 작동하는지 매우 단순화 된 예를 제공하려면 :

응용 프로그램은 운영 체제에 파일에 무언가를 쓰도록 지시합니다. 응용 프로그램에 운영 체제는 파일 및 디렉토리와 같은 개념을 제공합니다.

하드웨어에는 이러한 개념이 없습니다. 하드웨어는 512 바이트의 고정 블록으로 분할 된 디스크와 같은 개념을 제공합니다. 운영 체제는 파일에 사용할 블록과 파일 이름, 크기 및 디스크 위치와 같은 메타 데이터에 대한 다른 블록을 결정합니다. 그런 다음 하드웨어에 다음과 같이 알려줍니다.이 512 바이트를 디스크에이 번호가있는 섹터에 해당 번호의 디스크에 기록하십시오. 디스크에이 같은 다른 번호를 가진 다른 512 바이트를 섹터에 쓰십시오. 등등.

운영 체제가 하드웨어에 지시하는 방식은 매우 다양합니다. 운영 체제의 기능 중 하나는 이러한 차이점으로부터 응용 프로그램을 보호하는 것입니다. 디스크 종류의 경우 한 종류의 하드웨어에서 운영 체제는 디스크 및 섹터 번호를 I / O 포트에 쓴 다음 바이트를 하나씩 별도의 I / O 포트에 씁니다. 다른 종류의 하드웨어에서 운영 체제는 섹터의 전체 512 바이트를 메모리 영역에 복사하고 해당 메모리 영역의 위치를 ​​특수 메모리 위치에 기록한 다음 디스크와 섹터 번호를 다른 영역에 기록해야합니다. 특별한 메모리 위치.


오늘날의 고급 하드웨어는 매우 복잡합니다. 모든 프로그래밍 세부 사항을 제공하는 매뉴얼은 수천 페이지의 도어 스토퍼입니다. 예를 들어, 최신 Intel CPU 매뉴얼은 7 페이지로 총 4000 페이지가 넘으며 이는 CPU에만 해당됩니다. 대부분의 다른 구성 요소는 메모리 또는 I / O 포트 블록을 노출하며 운영 체제는 CPU가 주소 공간 내의 주소에 매핑하도록 지시 할 수 있습니다. 이러한 구성 요소 중 일부는 몇 개의 I / O 포트 나 메모리 주소 뒤에 더 많은 것을 노출합니다. 예를 들어, RTC (실시간 시계, 전원이 꺼진 상태에서 컴퓨터의 시간을 유지하는 구성 요소)는 한 쌍의 I / O 포트 뒤에 몇 백 바이트의 메모리를 노출 시키며 이는 매우 간단한 구성 요소입니다. 원래 PC / AT. 하드 디스크와 같은 것들은 완전히 분리 된 프로세서를 가지고 있습니다. 운영 체제가 표준화 된 명령을 통해 통신합니다. GPU는 훨씬 더 복잡합니다.

위의 의견에서 여러 사람들이 Arduino를 제안했습니다. USB 커넥터를 직렬 포트로 노출시키는 것을 제외하고 Arduino Uno의 모든 작업을 수행하는 ATmega328은 수백 페이지의 매뉴얼 만 가지고 있습니다. Arduino에서는 운영 체제가없는 하드웨어에서 직접 실행됩니다. 원하지 않는 경우 사용할 필요가없는 몇 가지 작은 라이브러리 루틴.


1

실행 가능한 예제

기술적으로 OS없이 실행되는 프로그램은 OS입니다. 이제 몇 가지 작은 hello world OS를 만들고 실행하는 방법을 살펴 보겠습니다.

아래 모든 예제 코드는 이 GitHub 리포지토리에 있습니다.

부트 섹터

x86에서 수행 할 수있는 가장 단순하고 가장 낮은 수준의 작업은 부팅 섹터 유형 인 MBR (Master Boot Sector)을 만든 다음 디스크에 설치하는 것입니다.

여기서 우리는 단일 printf호출로 하나를 만듭니다 .

printf '\364%509s\125\252' > main.img
sudo apt-get install qemu-system-x86
qemu-system-x86_64 -hda main.img

결과:

여기에 이미지 설명을 입력하십시오

Ubuntu 18.04, QEMU 2.11.1에서 테스트되었습니다.

main.img 다음을 포함합니다 :

  • \3648 진수 == 0xf416 진수 : hlt명령어 인코딩으로 CPU가 작동을 중지하도록 지시합니다.

    따라서 우리의 프로그램은 아무것도하지 않을 것입니다 : 시작과 중지 만.

    \xPOSIX에서 16 진수를 지정하지 않기 때문에 8 진수를 사용 합니다.

    이 인코딩을 쉽게 얻을 수 있습니다 :

    echo hlt > a.asm
    nasm -f bin a.asm
    hd a
    

    그러나 0xf4인코딩은 인텔 설명서에도 문서화되어 있습니다.

  • %509s509 개의 공간을 생성합니다. 바이트 510까지 파일을 채워야합니다.

  • \125\252octal == 0x55다음에 0xaa: 하드웨어에 필요한 매직 바이트. 바이트 511 및 512 여야합니다.

    존재하지 않으면 하드웨어는이 디스크를 부팅 가능한 디스크로 취급하지 않습니다.

아무 것도하지 않아도 화면에 이미 몇 개의 문자가 인쇄되어 있습니다. 펌웨어로 인쇄되며 시스템을 식별하는 역할을합니다.

실제 하드웨어에서 실행

에뮬레이터는 재미 있지만 하드웨어는 정말 중요합니다.

그러나 이것은 위험하므로 실수로 디스크를 지울 수 있습니다. 중요한 데이터가 포함되지 않은 오래된 시스템에서만이 작업을 수행하십시오! 또는 Raspberry Pi와 같은 devboard는 아래 ARM 예를 참조하십시오.

일반적인 랩톱의 경우 다음과 같은 작업을 수행해야합니다.

  • 이미지를 USB 스틱에 굽습니다 (데이터가 손상 될 수 있습니다).

    sudo dd if=main.img of=/dev/sdX
    
  • 컴퓨터에 USB를 연결

  • 전원을 켜십시오

  • USB에서 부팅하도록 지시하십시오.

    즉, 펌웨어가 하드 디스크보다 먼저 USB를 선택하도록합니다.

    이것이 시스템의 기본 동작이 아닌 경우 전원을 켠 후 Enter 키, F12, ESC 또는 기타 이상한 키를 계속 누르면 USB에서 부팅하도록 선택할 수있는 부팅 메뉴가 나타납니다.

    해당 메뉴에서 검색 순서를 구성하는 것이 종종 가능합니다.

예를 들어, 이전 Lenovo Thinkpad T430, UEFI BIOS 1.16에서 다음을 볼 수 있습니다.

안녕하세요 세계

최소한의 프로그램을 만들었으므로 이제 hello world로 넘어 갑시다.

분명한 질문은 IO를 수행하는 방법입니다. 몇 가지 옵션 :

  • 펌웨어를 요청하십시오 (예 : BIOS 또는 UEFI)
  • VGA : 쓰면 화면에 인쇄되는 특수 메모리 영역입니다. 보호 모드에서 사용할 수 있습니다.
  • 드라이버를 작성하고 디스플레이 하드웨어와 직접 대화하십시오. 이것은 "적절한"방법으로보다 강력하지만 복잡합니다.
  • 직렬 포트 . 이것은 호스트 터미널에서 문자를 보내고 검색하는 매우 간단한 표준화 된 프로토콜입니다.

    소스 .

    불행히도 대부분의 최신 랩톱에는 노출되지 않지만 개발 보드를 사용하는 일반적인 방법입니다 (아래 ARM 예 참조).

    이러한 인터페이스는 예를 들어 Linux 커널을 디버깅하는 데 실제로 유용 하기 때문에 이것은 정말 부끄러운 일 입니다.

  • 칩의 디버그 기능을 사용하십시오. ARM은 예를 들어 세미 호스팅 을 호출합니다 . 실제 하드웨어에서는 추가 하드웨어 및 소프트웨어 지원이 필요하지만 에뮬레이터에서는 무료로 편리한 옵션이 될 수 있습니다. .

여기서는 x86에서 더 간단한 BIOS 예제를 수행 할 것입니다. 그러나 가장 강력한 방법은 아닙니다.

main.S

.code16
    mov $msg, %si
    mov $0x0e, %ah
loop:
    lodsb
    or %al, %al
    jz halt
    int $0x10
    jmp loop
halt:
    hlt
msg:
    .asciz "hello world"

link.ld

SECTIONS
{
    . = 0x7c00;
    .text :
    {
        __start = .;
        *(.text)
        . = 0x1FE;
        SHORT(0xAA55)
    }
}

조립 및 연결 :

gcc -c -g -o main.o main.S
ld --oformat binary -o main.img -T linker.ld main.o

결과:

여기에 이미지 설명을 입력하십시오

테스트 대상 : Lenovo Thinkpad T430, UEFI BIOS 1.16. Ubuntu 18.04 호스트에서 생성 된 디스크.

표준 사용자 랜드 어셈블리 지침 외에도 다음과 같은 이점이 있습니다.

  • .code16: 16 비트 코드를 출력하도록 GAS에 지시

  • cli: 소프트웨어 인터럽트를 비활성화합니다. 그 후 프로세서가 다시 실행되기 시작할 수 있습니다.hlt

  • int $0x10: BIOS 호출을 수행합니다. 문자를 하나씩 인쇄합니다.

중요한 링크 플래그는 다음과 같습니다.

  • --oformat binary: 원시 이진 어셈블리 코드를 출력합니다. 일반 사용자 실행 파일의 경우와 같이 ELF 파일 내에서 워프하지 마십시오.

조립 대신 C 사용

C는 어셈블리로 컴파일되기 때문에 표준 라이브러리없이 C를 사용하는 것은 매우 간단하므로 기본적으로 다음이 필요합니다.

  • 올바른 장소에 메모리에 물건을 넣는 링커 스크립트
  • GCC가 표준 라이브러리를 사용하지 않도록 지시하는 플래그
  • 에 필요한 C 상태를 설정하는 작은 어셈블리 진입 점 main, 특히
    • 스택
    • BSS 제로

TODO : GitHub에서 x86 예제를 링크하십시오. 여기 내가 만든 ARM이 있습니다.

POSIX를 통해 많은 C 표준 라이브러리 기능 구현하는 Linux 커널이 없기 때문에 표준 라이브러리를 사용하려는 경우 상황이 더 재미있어집니다 .

리눅스와 같은 본격적인 OS를 사용하지 않고 몇 가지 가능성은 다음과 같습니다.

  • 뉴립

    자세한 예 : https://electronics.stackexchange.com/questions/223929/c-standard-libraries-on-bare-metal/223931

    Newlib에서는 syscall을 직접 구현해야하지만 최소한의 시스템 만 있으면 쉽게 구현할 수 있습니다.

    예를 들어 printfUART 또는 ARM 시스템으로 리디렉션 하거나 semihosting으로 구현할 수 exit()있습니다 .

  • FreeRTOSZephyr 와 같은 임베디드 운영 체제 .

    이러한 운영 체제에서는 일반적으로 선제 예약을 해제 할 수 있으므로 프로그램 실행 시간을 완전히 제어 할 수 있습니다.

    그것들은 일종의 사전 구현 된 Newlib로 볼 수 있습니다.

ARM에서는 일반적인 아이디어가 동일합니다. 나는 업로드했다 :

Raspberry Pi의 경우 https://github.com/dwelch67/raspberrypi 는 오늘날 가장 인기있는 자습서처럼 보입니다.

x86과의 차이점은 다음과 같습니다.

  • IO 직접 마법 주소로 작성하여 수행됩니다, 어떤이없는 inout지침을.

    이것을 메모리 매핑 된 IO 라고 합니다 .

  • Raspberry Pi와 같은 실제 하드웨어의 경우 디스크 이미지에 펌웨어 (BIOS)를 직접 추가 할 수 있습니다.

    펌웨어 업데이트가 더 투명 해지기 때문에 좋은 일입니다.

펌웨어

사실, 부트 섹터는 시스템의 CPU에서 실행되는 최초의 소프트웨어가 아닙니다.

실제로 가장 먼저 실행 되는 것은 소위 펌웨어 이며 소프트웨어입니다.

  • 하드웨어 제조업체가 만든
  • 일반적으로 비공개 소스이지만 아마도 C 기반
  • 읽기 전용 메모리에 저장되므로 공급 업체의 동의 없이는 수정하기가 어렵거나 불가능합니다.

잘 알려진 펌웨어는 다음과 같습니다.

  • BIOS : 기존의 모든 x86 펌웨어 SeaBIOS는 QEMU에서 사용하는 기본 오픈 소스 구현입니다.
  • UEFI : BIOS의 후속 버전으로,보다 표준화되었지만, 성능이 뛰어나고 엄청나게 부 풀었습니다.
  • Coreboot : 고귀한 크로스 아치 오픈 소스 시도

펌웨어는 다음과 같은 작업을 수행합니다.

  • 부팅 가능한 것을 찾을 때까지 각 하드 디스크, USB, 네트워크 등을 반복합니다.

    QEMU를 실행 하면 하드웨어에 연결된 하드 디스크 -hda라고합니다.main.img

    hda 시도 할 첫 번째이며 사용됩니다.

  • 처음 512 바이트를 RAM 메모리 주소에로드하고 0x7c00CPU의 RIP를 거기에 놓고 실행 시키십시오.

  • 부팅 메뉴 또는 BIOS 인쇄 호출과 같은 것을 디스플레이에 표시

펌웨어는 대부분의 OS가 의존하는 OS와 유사한 기능을 제공합니다. 예를 들어 Python 하위 세트가 BIOS / UEFI에서 실행되도록 포팅되었습니다 : https://www.youtube.com/watch?v=bYQ_lq5dcvM

펌웨어는 OS와 구별 할 수 없으며 펌웨어가 유일하게 할 수있는 유일한 "진정한"베어 메탈 프로그래밍이라고 주장 할 수 있습니다.

CoreOS 개발자는 다음과 같이 말합니다 .

어려운 부분

PC 전원을 켤 때 칩셋 (노스 브리지, 사우스 브리지 및 SuperIO)을 구성하는 칩이 아직 제대로 초기화되지 않았습니다. BIOS ROM이 가능한 한 CPU에서 제거되었지만 CPU가 액세스 할 수 있어야합니다. 그렇지 않으면 CPU가 실행할 명령이 없기 때문입니다. 그렇다고 BIOS ROM이 완전히 매핑되지 않았다는 의미는 아닙니다. 그러나 부팅 프로세스를 진행하기에 충분한 매핑입니다. 다른 장치는 잊어 버리십시오.

QEMU에서 Coreboot를 실행하면 더 높은 계층의 Coreboot와 페이로드를 실험 할 수 있지만 QEMU는 낮은 수준의 시작 코드를 실험 할 기회가 거의 없습니다. 우선, RAM은 처음부터 바로 작동합니다.

BIOS 초기 상태

하드웨어의 많은 것들과 마찬가지로, 표준화는 약하고, 의존 하지 말아야 할 것 중 하나는 BIOS 후에 코드가 실행되기 시작할 때 레지스터의 초기 상태입니다.

따라서 자신에게 호의를 베풀고 다음과 같은 초기화 코드를 사용 하십시오 . https://stackoverflow.com/a/32509555/895245

레지스터 는 중요한 부작용을 좋아 %ds하고 %es있으므로 명시 적으로 사용하지 않더라도 제로를 제거해야합니다.

일부 에뮬레이터는 실제 하드웨어보다 좋고 초기 상태가 좋습니다. 그런 다음 실제 하드웨어에서 실행하면 모든 것이 깨집니다.

GNU GRUB 멀티 부트

부팅 섹터는 간단하지만 매우 편리하지는 않습니다.

  • 디스크 당 하나의 OS 만 가질 수 있습니다
  • 로드 코드는 실제로 작고 512 바이트에 맞아야합니다. 이것은 int 0x13 BIOS 호출 로 해결할 수 있습니다 .
  • 보호 모드로 이동하는 것과 같이 많은 시작을 직접해야합니다

이런 이유로 GNU GRUB 은 multiboot라는보다 편리한 파일 형식을 만들었습니다.

최소 작업 예 : https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/hello-world

또한 GitHub 예제 리포지토리 에서 사용하여 USB를 백만 번 불 태우지 않고도 실제 하드웨어에서 모든 예제를 쉽게 실행할 수 있습니다. QEMU에서는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

OS를 멀티 부팅 파일로 준비하면 GRUB은 일반 파일 시스템에서 OS를 찾을 수 있습니다.

이것이 대부분의 배포판에서하는 일이며 OS 이미지는 아래에 /boot있습니다.

멀티 부트 파일은 기본적으로 특수 헤더가있는 ELF 파일입니다. GRUB은 https://www.gnu.org/software/grub/manual/multiboot/multiboot.html 에서 지정합니다.

을 사용하여 멀티 부팅 파일을 부팅 가능한 디스크로 전환 할 수 있습니다 grub-mkrescue.

엘 토리 토

CD에 구울 수있는 형식 : https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29

ISO 또는 USB에서 작동하는 하이브리드 이미지를 생성 할 수도 있습니다. 이것은 grub-mkrescue( )를 make isoimage사용하여 수행 할 수 있으며 Linux 커널을 사용하여 수행 할 수도 있습니다 isohybrid.

자원

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.