オペレーティング システムを自分で作成する方法。 オペレーティング システムを最初から作成する方法。 関数 - キーボード割り込みハンドラー

オペレーティング システムを作成するために知っておくべきこと

オペレーティング システムの作成は、コンピューターの動作方法に関する広範囲かつ複雑な知識が必要となるため、プログラミングの中で最も困難なタスクの 1 つです。 どれ? 以下で調べてみましょう。

OSとは

オペレーティング システム (OS) は、コンピュータ ハードウェアとそのリソースを操作して動作するソフトウェアであり、コンピュータのハードウェアとソフトウェアの間の橋渡しをします。

第一世代のコンピューターにはオペレーティング システムがありませんでした。 最初のコンピュータ上のプログラムには、システムの直接操作、周辺機器との通信、計算のためのコードが含まれており、このプログラムはそのために書かれました。 このような状況のため、ロジックが単純なプログラムであってもソフトウェアで実装することは困難でした。

コンピュータがより多様で複雑になるにつれて、OS とアプリケーションの両方として機能するプログラムを作成するのは単純に不便になりました。 したがって、プログラムを書きやすくするために、コンピュータの所有者はソフトウェアを開発し始めました。 これがオペレーティングシステムの登場です。

OS は、ユーザー プログラムの実行に必要なものをすべて提供します。 これらの出現は、プログラムがコンピュータ上の作業全体を制御する必要がなくなったことを意味します (これはカプセル化の優れた例です)。 プログラムはオペレーティング システムと連携する必要があり、システム自体がリソースを処理し、周辺機器 (キーボード、プリンタ) と連携するようになりました。

オペレーティング システムの簡単な歴史

C言語

上で述べたように、OS を作成するための高級プログラミング言語はいくつかあります。 ただし、その中で最も人気があるのは C です。

ここからこの言語の学習を始めることができます。 このリソースでは、基本概念を紹介し、より高度なタスクに備えることができます。

「Learn C the Hard Way」は別の本のタイトルです。 通常の理論に加えて、多くの実践的な解決策が含まれています。 このチュートリアルでは、言語のあらゆる側面をカバーします。

または、次のいずれかの書籍を選択することもできます。

  • 「The C Programming Language」カーニハンとリッチー著。
  • 『C プログラミング絶対初心者ガイド』Parry と Miller 著。

OS開発

コンピューター サイエンス、アセンブリ言語、C について知っておくべきことをすべてマスターしたら、OS の直接開発に関する本を少なくとも 1 ~ 2 冊読む必要があります。 これに関するリソースは次のとおりです。

「ゼロからの Linux」。 ここでは、Linux オペレーティング システムを組み立てるプロセスについて説明します (教科書はロシア語を含む多くの言語に翻訳されています)。 他の教科書と同様に、ここでも必要な基礎知識がすべて提供されます。 これらを頼りに、OSの作成に挑戦してみましょう。 OS のソフトウェア部分をより専門的なものにするために、教科書に次の追加があります。

x86 システム用のカーネルを作成するためのガイド。 パート 1. 核心部分のみ

x86 システム上で GRUB ブートローダーを使用して起動できる単純なカーネルを作成してみましょう。 このカーネルは画面にメッセージを表示して待機します。

x86 システムはどのようにブートするのでしょうか?

カーネルの作成を開始する前に、システムがどのように起動してカーネルに制御を転送するかを理解しましょう。

ほとんどのプロセッサ レジスタには、起動時にすでに特定の値が含まれています。 命令のアドレスを指すレジスタ (命令ポインタ、EIP) には、プロセッサによって実行される命令が存在するメモリ アドレスが格納されます。 デフォルトの EIP は次のとおりです。 0xFFFFFFFF0。 したがって、ハードウェア レベルの x86 プロセッサはアドレス 0xFFFFFFF0 で動作を開始します。 これは実際には 32 ビット アドレス空間の最後の 16 バイトです。 このアドレスはリセットベクタと呼ばれます。

チップセットのメモリ マップにより、0xFFFFFFF0 が RAM ではなく BIOS の特定の部分に属することが保証されるようになりました。 このとき、BIOS はアクセスを高速化するために自身を RAM にコピーします。 アドレス 0xFFFFFFF0 には、BIOS のコピーが保存されているメモリ内のアドレスにジャンプする命令のみが含まれます。

これにより、BIOS コードの実行が開始されます。 BIOS はまず、事前に設定された順序で起動できるデバイスを探します。 デバイスが起動可能かどうかを決定するマジックナンバーが見つかりました (最初のセクターの 511 番目と 512 番目のバイトは以下に等しい必要があります) 0xAA55).

BIOS はブート デバイスを見つけると、デバイスの最初のセクターの内容を物理アドレスから RAM にコピーします。 0x7c00; 次に、そのアドレスにアクセスして、ダウンロードしたコードを実行します。 このコードは次のように呼ばれます ブートローダー.

ブートローダーはカーネルを物理アドレスにロードします。 0x100000。 このアドレスは、x86 システム上のすべての大規模カーネルで開始アドレスとして使用されます。

すべての x86 プロセッサは、最初は 16 ビット モードと呼ばれる単純な 16 ビット モードで開始します。 リアルモード。 GRUB ブートローダーがモードを 32 ビットに切り替える 保護モード、レジスタ CR0 の下位ビットを次のように設定します。 1 。 したがって、カーネルは 32 ビット保護モードでロードされます。

Linux カーネルの場合、GRUB は Linux ブート プロトコルを認識し、カーネルをリアル モードでブートすることに注意してください。 カーネルは自動的に保護モードに切り替わります。

私たちは何が必要なのか?

  • x86 コンピューター。
  • Linux;
  • ld (GNU リンカー);

アセンブラでのエントリポイントの設定

どれだけ C だけに限定したいとしても、アセンブラーで何かを記述する必要があります。 カーネルの開始点として機能する小さなファイルをそこに書き込みます。 実行されるのは、C で書かれた外部関数を呼び出し、プログラム フローを停止することだけです。

このコードが開始点であることを確認するにはどうすればよいでしょうか?

オブジェクト ファイルをリンクするリンカー スクリプトを使用して、最終的な実行可能ファイルを作成します。 このスクリプトでは、アドレス 0x100000 にデータをロードすることを明示的に示します。

アセンブラコードは次のとおりです。

;;kernel.asm ビット 32 ;nasm ディレクティブ - 32 ビット セクション .text global start extern kmain ;kmain は C ファイルで定義されます start: cli ;ブロック割り込み mov esp, stack_space ;set スタック ポインタ呼び出し kmain hlt ;CPU セクションを停止します.bss resb 8192 ;スタック stack_space の 8KB:

最初の命令のビット 32 は、x86 アセンブリ命令ではありません。 これは、32 ビット モードで動作するプロセッサのコード生成を指定する NASM アセンブラへのディレクティブです。 私たちの場合、これは必須ではありませんが、一般的には便利です。

コードのセクションは 2 行目から始まります。

global は、ソース コード シンボルをグローバルにするもう 1 つの NASM ディレクティブです。 このようにして、リンカは開始シンボルがどこにあるか、つまりエントリ ポイントを認識します。

kmain は、kernel.c ファイルで定義される関数です。 extern は、関数が別の場所で宣言されていることを意味します。

次に、start 関数が来ます。この関数は、kmain 関数を呼び出し、hlt 命令でプロセッサを停止します。 このため、cli 命令を使用して事前に割り込みを無効にします。

理想的には、メモリを割り当て、スタック ポインタ (esp) でそれを指す必要があります。 ただし、GRUB がすでにこれを行っているようです。 ただし、BSS セクションにある程度のスペースを割り当て、スタック ポインタをその先頭に移動します。 指定されたバイト数を予約する resb 命令を使用します。 kmain を呼び出す直前に、mov 命令を使用してスタック ポインター (esp) が正しい位置に設定されます。

C のカーネル

kernel.asm では、kmain() 関数を呼び出しました。 したがって、「C」コードは kmain() で実行を開始する必要があります。

/* * kernel.c */ void kmain(void) ( const char *str = "最初のカーネル"; char *vidptr = (char*)0xb8000; //ビデオメモリはここから始まります。 unsigned int i = 0; unsigned int j = 0; /* このループは画面をクリアします * 80 列のそれぞれに 25 行があり、各要素は 2 バイトかかります */ while(j< 80 * 25 * 2) { /* blank character */ vidptr[j] = " "; /* attribute-byte - light grey on black screen */ vidptr = 0x07; j = j + 2; } j = 0; /* this loop writes the string to video memory */ while(str[j] != "\0") { /* the character"s ascii */ vidptr[i] = str[j]; /* attribute-byte: give character black bg and light grey fg */ vidptr = 0x07; ++j; i = i + 2; } return; }

私たちのカーネルが行うことは、画面をクリアして「my first kernel」という行を表示することだけです。

まず、アドレスを指す vidptr ポインターを作成します。 0xb8000。 プロテクトモードでは、「ビデオメモリ」はこのアドレスから始まります。 画面にテキストを表示するために、0xb8000 から始まる 80 個の ASCII 文字を 25 行予約します。

各文字は通常の 8 ビットではなく 16 ビットで表示されます。最初のバイトには文字自体が格納され、2 番目のバイトには属性バイトが格納されます。 文字の色などの書式を記述します。

黒の背景に緑の文字 s を表示するには、最初のバイトにこの文字を書き込み、2 番目のバイトに値 0x02 を書き込みます。 0 は背景が黒、2 は文字色が緑を意味します。

カラーチャートは次のとおりです。

0 - ブラック、1 - ブルー、2 - グリーン、3 - シアン、4 - レッド、5 - マゼンタ、6 - ブラウン、7 - ライトグレー、8 - ダークグレー、9 - ライトブルー、10/a - ライトグリーン、 11/b - ライトシアン、12/c - ライトレッド、13/d - ライトマゼンタ、14/e - ライトブラウン、15/f - ホワイト。

私たちのカーネルでは、黒い背景に明るい灰色のテキストを使用するため、属性バイトの値は 0x07 になります。

最初のループでは、プログラムは 80x25 ゾーン全体に空白のシンボルを印刷します。 これにより画面が消去されます。 次のサイクルでは、0x07 に等しい属性バイトを持つヌル終了文字列「my first kernel」の文字が「ビデオ メモリ」に書き込まれます。 これにより、文字列が画面に表示されます。

接続部

NASM を使用して、kernel.asm をオブジェクト ファイルにアセンブルする必要があります。 次に、GCC を使用して kernel.c を別のオブジェクト ファイルにコンパイルします。 次に、それらを実行可能なブート カーネルにアタッチする必要があります。

これを行うには、引数として ld に渡されるバインディング スクリプトを使用します。

/* * link.ld */ OUTPUT_FORMAT(elf32-i386) ENTRY(start) SECTIONS ( . = 0x100000; .text: ( *(.text) ) .data: ( *(.data) ) .bss: ( *( .bss) ) )

まず最初に尋ねます 出力フォーマット 32 ビットの実行可能およびリンク可能フォーマット (ELF) として。 ELF は、Unix x86 システムの標準バイナリ ファイル形式です。 エントリは、エントリ ポイントであるシンボルの名前を指定する 1 つの引数を取ります。 セクション- これが最も重要な部分です。 実行可能ファイルのマークアップを定義します。 さまざまなセクションをどのように接続し、どこに配置するかを決定します。

SECTIONS の後の括弧内には、ドット (.) が位置カウンターを表示します。デフォルトは 0x0 です。 それは変えることができます、それが私たちが取り組んでいることです。

次の行を見てみましょう: .text: ( *(.text) ) 。 アスタリスク (*) は、任意のファイル名に一致する特殊文字です。 式 *(.text) は、すべての入力ファイルのすべての .text セクションを意味します。

したがって、リンカは、オブジェクト ファイルのすべてのコード セクションを、位置カウンタ (0x100000) のアドレスで実行可能ファイルの 1 つのセクションに結合します。 この後、カウンター値は 0x100000 + 結果のセクションのサイズと等しくなります。

他のセクションでも同じことが起こります。

GRUBとマルチブート

これで、すべてのファイルでカーネルを作成する準備が整いました。 しかし、あと一歩が残っています。

と呼ばれるブートローダーを使用して x86 カーネルをブートするための標準があります。 マルチブート仕様。 GRUB は、カーネルがこれらの仕様を満たしている場合にのみ起動します。

これらに続いて、カーネルの最初の 8 キロバイトにヘッダーが含まれている必要があります。 さらに、このヘッダーには 3 つのフィールド (4 バイト) が含まれている必要があります。

  • 魔法のフィールド: マジックナンバーが含まれます 0x1BADB002核心を特定するために。
  • 分野 フラグ: 必要ないのでゼロに設定します。
  • 分野 チェックサム: 前の 2 つに加算すると、ゼロが得られるはずです。

kernel.asm は次のようになります。

;;kernel.asm ;nasm ディレクティブ - 32 ビット bits 32 セクション .text ;マルチブート仕様アライン 4 dd 0x1BADB002 ;magic dd 0x00 ;flags dd - (0x1BADB002 + 0x00) ;チェックサム。 m+f+c はゼロでなければなりません global start extern kmain ;kmain は c ファイルで定義されます start: cli ;ブロック割り込み mov esp、stack_space ;スタック ポインタを設定します kmain hlt ;CPU セクションを停止します .bss resb 8192 ;スタック用 8KBスタックスペース:

コアの構築

次に、kernel.asm と kernel.c からオブジェクト ファイルを作成し、スクリプトを使用してそれらをリンクします。

Nasm -f elf32 kernel.asm -o kasm.o

この行はアセンブラを実行して、ELF-32 形式の kasm.o オブジェクト ファイルを作成します。

Gcc -m32 -c kernel.c -o kc.o

「-c」オプションを使用すると、コンパイル後に隠しリンクが発生しないことが保証されます。

Ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o

これにより、スクリプトを使用してリンカーが実行され、という実行可能ファイルが作成されます。 カーネル.

grubをセットアップしてカーネルを起動する

GRUB では、kernel- パターンを満たすカーネル名が必要です。 。 そこでカーネルの名前を変更します。 私は kernel-701 という名前を付けました。

今それをディレクトリに入れてください /ブート。 これを行うには、スーパーユーザー権限が必要です。

GRUB 構成ファイル grub.cfg に次の内容を追加します。

タイトル myKernel root (hd0,0) kernel /boot/kernel-701 ro

hiddenmenu ディレクティブが存在する場合は、忘れずに削除してください。

コンピュータを再起動すると、自分のカーネルを含むカーネルのリストが表示されます。 それを選択すると、次の内容が表示されます。

これがあなたの核心です! I/O システムを追加しましょう。

追伸

  • カーネルを使用する場合は、仮想マシンを使用することをお勧めします。
  • カーネルを実行するには グラブ2設定は次のようになります: menuentry "kernel 7001" ( set root="hd0,msdos1" multiboot /boot/kernel-7001 ro )
  • qemu エミュレータを使用したい場合は、qemu-system-i386 -kernel kernel を使用します。

「NT」という略語はマーケティングでは「New Technologies」を意味しますが、設計ドキュメントではまったく異なる意味でした。 実際、Windows NT は、1988 年にはまだリリースされていなかった新しい Intel i860 プロセッサ用に開発されました。 コードネームは「N10」( N Tエン)。

最初のバージョンである Windows NT 3.1 は 5 年後の 1993 年に登場しました。 この時点で、チームにはすでに 250 人の開発者がいた。

今日のWindows

  • 10億人のユーザー
  • 1 億 4,000 万行のコード (テスト コードとツールを含む)
    Windows のコードは大きく異なります。 20 年前に書かれた部分もあれば、現在のバージョンでのみ登場する部分もあります。 たとえば、Windows Vista の Web Services on Devices (WSD) コードは最初のバージョンであり、GDI コードは開発の最終段階にあり、ほとんど変更されていません。DirectX コードはすでに十分に開発されていますが、現在積極的に変更されています。時間。
  • 8000人の開発者
  • 36 のローカリゼーション言語
  • 20年の開発

Windows開発

20 ~ 30 年前、プログラミングの方法論は「ウォーターフォール」の 1 つだけが使用されていました。 それは次のようなシーケンスです。

仕様→設計→実装→テスト→納品。

ただし、この方法論は小規模なプロジェクトでのみ機能します。 現在の Windows のような製品には、次のようなさまざまな方法論が必要です。

  • 製品サイクルモデル
  • チームソフトウェアプロセス
  • 「エクストリームプログラミング」

これらの方法論にはすべて長所と短所の両方があります。 チームの規模とコンポーネントの開発段階に応じて、さまざまな Windows 開発チームが異なる開発手法を使用します。
Windows の場合、製品全体として、製品サイクル モデルが使用されます。

  • 3~4ヶ月の期間
  • 期間内 - 「滝」

この規模の製品を開発する場合の最大の課題は、開発に時間がかかることです。 初期段階では、現時点で存在する問題を既存の手段を使用して解決します。 しかし、唯一変わらないことは、すべては変化するということです。 長年の開発を通じて:

  • 要件が変わります
  • チャンスは変わる
  • 仕事のスケジュールが変わります
  • プロジェクトが変わります
  • ユーザーも変わるだろうし

チームが異なれば開発方法も異なりますが、「普遍的な」ルールがあります。

  • 多数のテスター向けの中間バージョン (マイルストーン、ベータ、CTP) のリリース
  • 内部組立を短サイクル(1日)でリリース
  • 設計のシンプルさと信頼性
  • 個人およびチームのコードレビュー
  • 単体テスト
  • ビルド検証テスト
  • 中間アセンブリは高品質でなければなりません (書かれたものは機能する必要があります)

私自身、自宅のコンピューターのメイン OS として Windows 7 ビルド 6801 を 1 か月間使用して作業した結果、このビルドに対して肯定的な印象を抱いたことを書き留めておきたいと思います。

Windows 開発プロセス全体は、毎日のビルドを中心に構築されています。

  • これが製品のパルスです
  • 開発は決して止まらない
  • 毎日の自動テスト
  • 初期段階での統合
  • 開発者の責任
  • 製品の明らかな状態

かつて、ソース コード ブランチは 1 つだけであり、すべての開発者はそこに直接変更を加えていました。 今では開発チームが大きすぎて機能しません。 多くのブランチがサポートされており、その中にはメインのブランチ、WinMain があります。 各ラボには独自のローカル開発ブランチがあり、そこに変更が統合されます。 テストされた変更は最終的に WinMain に統合されます。

毎日の開発サイクル:

  • 15:00 - ソース コード管理システムへの統合が承認された変更
  • ビルド 6 バージョン (無料/チェック済み - x86、x64、IA64)
  • 18:00 - 新しいバージョンがテストに利用可能になります
  • 新しいバージョンはテストのために数千台のワークステーションとサーバーにインストールされます
  • 自動ストレステスト
  • 05:00 - テストレポートが分析され、障害が診断されます
  • 09:00 - 概要レポートがチームに自動的に送信されます
  • 09:30 - 目標を設定するためのチームリーダーによる総括ミーティング

最上級マネージャーを含むすべてのプロジェクト参加者は、職場 (通常は自宅) のコンピューターで中間バージョンを使用します。

Windows は何で書かれていますか?

  • C、C++、C#、アセンブリ (x86、x64、IA64)
    アセンブラは、避けられない状況でかなり限定的に使用されます。
  • Visual Studio、ソースインサイト、ビルド、nmake
  • Source Depot - ソース管理システム
  • WinDbg、KD、NTSD - デバッガー

ビルドなどの多くの内部ツールは、microsoft.com/whdc/devtools からダウンロードできます。

Windows 7 カーネルの変更

Windows 7 カーネルには次の変更が加えられました。

  • リファクタリング
    Windows でグラフィック サブシステムを削除できないのはなぜですか?
    技術的な観点から見たこの質問に対する答えは、Windows のグラフィック サブシステムは独立したものではなく、Win32 サブシステムの一部であるということです。
    Windows 7 では、依存関係を解消するために多くの低レベル コンポーネントがリファクタリングされました。 これはユーザーには目立ちません。新しい DLL のみが表示されます。たとえば、kernel32.dll は kernel32.dll と kernelbase.dll に分割されました。
    このパーティショニングにより、MinWin と呼ばれる最小限のカーネル (ディスク上に 20 メガバイト) を割り当てることが可能になりました。
  • x86 および x64 の EFI サポート (Vista SP1 と同じ)
    多くのメーカーは、EFI を支持して BIOS を廃止しようとしています。
  • VHD (仮想ハードディスク) からの起動
  • デバイスの並行初期化とサービスの開始
    Windows の起動時、デバイス ツリーの構築にはかなりの時間がかかります。 PNP マネージャーは、バス ドライバー (PCI、USB、FireWire など) をポーリングして、どのようなデバイスがあるかを確認する必要があります。 そして、ほとんどの時間、プロセッサはデバイスが応答する (または応答しない) のを待ちます。 結局のところ、バス上のデバイスを識別するには、デバイスをポーリングする必要があります。 応答している場合は応答しますが、応答していない場合は、プロセッサがアイドル状態になるまで待つ必要があります。 これらのタスクを並行して実行すると、読み込み時間が短縮されます。
  • スケジューラからディスパッチャ ロックを削除し、メモリ マネージャから PFN ロックを削除する
    過去数年間、プロセッサのクロック周波数は増加しておらず、開発はシングル コア レベルとシステム レベル (マルチコア) の両方で並列実行される命令の数を増やす方向に進んでいます。 この点で、スケーリングを改善するために多くの作業が行われてきました。
    カーネル内にあった 2 つの「最もホットな」ロック、Dispatcher ロックと PFN ロックが削除されました。
    ディスパッチャ ロックは、スレッドの状態が変化したときにスケジューラによって使用されました。 このロックは削除され、「待機中」スレッド状態はいくつかに分割されました。
    • 待機中: 進行中
    • 保留中: 完了
    • 待機中: キャンセルされました
    物理メモリ ページの属性を変更するときに PFN ロックが使用されました。 マルチプロセッサ システムでは、各プロセッサがこのロックへのアクセスを要求するため、膨大な時間がかかりました。
  • 256 個の論理プロセッサをサポート
    以前の Windows では、機械語がアフィニティ マスクとして使用されていました。 これは、空きプロセッサを見つけるのが非常に簡単だったために行われました。各ビットはプロセッサを表します。 したがって、32 ビット システムでは 32 個の論理プロセッサがサポートされ、64 ビット システムでは 64 個の論理プロセッサがサポートされました。
    Windows 7では、アフィニティマスクセグメントモデルへの移行により、256個の論理プロセッサのサポートが可能になりました。 プロセッサはグループ/セグメントに分類され始めました。 各グループには最大 64 個のプロセッサを含めることができます。 その結果、下位互換性が実現し、古いプログラムは 1 つのグループ内のプロセッサのみを「認識」し、新しいインターフェイスを使用する新しいプログラムはシステム内のすべてのプロセッサで動作します。
  • 省電力の向上: プロセッサ ソケットの無効化今日、ラップトップの所有者だけでなく、データセンターの所有者も、省エネルギーという深刻な問題に直面しています。 米国では、電力の 2% がコンピュータ データ センターで消費されています。 その多くは、ユーザーのアクティビティが少ない期間 (週末) にサーバーの一部をオフにします。
    複数のプロセッサ ソケットの 1 つのコアを無効にするよりも、プロセッサ ソケット全体を無効にするほうがはるかに有益であることがわかりました。 この場合、ソケット サポート インフラストラクチャ (メモリ コントローラー) 全体を無効にすることができます。

Windowsのメンテナンス、アップデート

以前は、更新は累積的なものが多かったです。 つまり、コンポーネントの初期の更新にバグのあるコードが含まれていた場合、後のバージョンにもそのコードが含まれることになります。 ただし、すべてのユーザーがすべてのアップデートを必要とするわけではなく、ユーザーごとに構成が異なります。

現在、Windows にはリリース後のソース コード (RTM) の 2 つのバージョンがあります。

  • RTM GDR (一般配布リリース)
    すべての人を対象としたいくつかの変更が含まれています。 主にセキュリティ修正です。
  • RTM LDR (限定配布リリース)
    更新プログラムをインストールするとき、Windows Update クライアントは必要なブランチを選択し、そこからコードをインストールします。

セキュリティアップデートの作成

セキュリティ更新プログラムを作成する作業は、脆弱性を特定することから始まります。 社内セキュリティ チーム、セキュリティ パートナー、開発者など、さまざまな検出方法が山ほどあります。 脆弱性が検出されると、2 つの並列プロセスが開始されます。

  • すべてのプラットフォーム向けの修正プログラムを開発中
  • 「オプション」で検索
    すべてのプラットフォームで同様の脆弱性を大規模に検索します。 同一のコードではなく、類似したコードを検索します。

修正が開発されると、コードレビューが始まります。 完了すると、修正がビルドに統合され、ビルドがテストのために送信されます。

  • コンポーネントの手動および自動テスト
  • ファイル形式の歪み、ネットワークコンポーネントなどの自動テスト。 (100万以上のオプション)
  • 下位互換性テストを含むシステム全体のテスト

すべての品質基準を満たす修正プログラムのみが Windows Update およびダウンロード センターでリリースできます。

  • 進む >

本題に入ると…

OS は、(通常は) マルチタスクを実装し、これらのタスク間および一般的なリソースの配分を管理するものです。 少なくとも、タスクが相互に悪影響を及ぼしたり、メモリの異なる領域で動作したり、デバイスを順番に操作したりできないようにする必要があります。 また、あるタスクから別のタスクにメッセージを送信する機能も提供する必要があります。

また、OS は、長期メモリがある場合、そのメモリへのアクセスを提供する必要があります。つまり、ファイル システムを操作するためのすべての機能を提供する必要があります。 最低限ですよ。

ほとんどの場合、最初のブート コードはアセンブリ言語で記述する必要があります。コードがどこにあるべきか、どのように見えるべきか、何をすべきか、そしてどのサイズを超えてはいけないかについて多くのルールがあります。

PC の場合、ASMA 上にブートローダーを記述する必要があります。ブートローダーは BIOS によって呼び出され、4 数百バイトを超えない範囲で何かを実行してメイン OS を起動し、メイン コードに制御を移します。近い将来は C で書くことができます。

ARMの場合、ACMA上に割り込みテーブル(リセット、各種エラー、IRQ、FIQ割り込みなど)を作成し、メインコードに制御を移す必要があります。 ただし、多くの開発環境では、このようなコードはほぼすべてのコントローラーで使用できます。

つまり、これには次のことが必要です。

  1. ターゲット プラットフォームのアセンブラを理解します。
  2. 希望のモードで動作するようにプロセッサを構成するために、プロセッサのアーキテクチャとあらゆる種類のサービス コマンドとレジスタを理解します。 PC では、これは、たとえば保護モードまたは 64 ビット モードへの移行です。ARM では、これはコアとペリフェラルのクロックを設定します。
  3. OS がどのように起動するか、どこにどのようにコードを書き込む必要があるかを正確に把握します。
  4. C 言語を知っている - 経験がなければ Asma で大規模なコードを書くのは難しく、それを維持するのはさらに難しくなります。 したがって、カーネルを C で記述する必要があります。
  5. OSの動作原理を理解する。 そうですね、このテーマに関するロシア語の本はたくさんありますが、どれも良いかどうかはわかりません。
  6. たくさんの忍耐力と忍耐力を持ってください。 間違いもあるでしょうし、それを見つけて修正する必要があります。 そして、たくさん読むことも必要になります。
  7. 時間はたっぷりあります。

さらに遠く。 あなたが何かを書いたとします。 これをテストする必要があります。 実験を行う物理デバイス (デバッグ ボード、2 台目のコンピュータ) か、そのためのエミュレータが必要です。 通常、2 番目の方が簡単かつ高速に使用できます。 PCの場合はVMWareなど。

よく検索すれば、インターネット上にもこのトピックに関する記事がたくさんあります。 ソース コードを備えた既製のオペレーティング システムの例も多数あります。

本当に望むのであれば、NT システム (Windows) の古いカーネルのソース コードを個別に (コメントとさまざまな種類の参考資料とともに Microsoft によって投稿された)、または古いカーネルと組み合わせて見ることもできます。 OS(流出)。

WikiHow は Wiki のように機能します。つまり、記事の多くは複数の著者によって書かれています。 この記事の作成には、匿名を含む 90 人が編集と改善に取り組みました。

オペレーティング システムは、数十万行のコードで構成されており、ユーザーはコンピューター ハードウェアと対話できるようになります。 これらは通常、プログラミング言語 C、C++、およびアセンブリで記述されます。

ステップ

    まずはプログラミングを学びます。アセンブラの知識が必要です。 また、C などの他の低レベル プログラミング言語についても理解しておくことを強くお勧めします。

    オペレーティング システムをロードするデバイスを決定します。これは、CD、DVD、フラッシュ メモリ デバイス、ハード ドライブ、または別のコンピュータである可能性があります。

    オペレーティング システムをどのようなものにするかを決定します。グラフィカル ユーザー インターフェイス (GUI) を備えた完全な OS にするべきでしょうか、それとももっとミニマルなものにするべきでしょうか? プロセスを開始する前に、どの方向に進むべきかを知っておく必要があります。

    オペレーティング システムがどのプロセッサ プラットフォームをサポートしているかを確認してください。 AI-32 と x86_64 はパーソナル コンピューターで最も一般的な 2 つのバージョンであるため、これらが最良の選択であると考えられます。

    すべてを最初から自分で行うことを好むか、またはシステム上に構築するベースとなるカーネルがあるかどうかを決定します。 Linux fromScratch は、たとえば独自の Linux ディストリビューションを作成したい人のためのプロジェクトです。

    独自のブートローダーを使用するか、事前に構築された Grand Unified Bootloader (GRUB) を使用するかを選択します。 独自のブート プログラムをコーディングするには、コンピューター ハードウェアと BIOS に関する広範な知識が必要となるため、ライブ カーネルのプログラミング スケジュールが遅れる可能性があります。

    使用するプログラミング言語を決定します。もちろん、Pascal や BASIC などの言語で OS を開発することも可能ですが、C またはアセンブリ言語で記述することが望ましいです。 オペレーティング システムの重要な部分にはアセンブリ言語の知識が必要となるため、アセンブリ言語は絶対に必要です。 一方、C++ には、OS のフルバージョンを実行するために必要なキーワードが含まれています。

    • C または C++ コードを使用して OS を構築するには、当然ながら、何らかのコンパイラを使用することになります。 これは、ソフトウェアにバンドルされているか、ディストリビュータの Web サイトで入手できる、選択した C/C++ コンパイラのマニュアル/説明書/ドキュメントを読む必要があることを意味します。 C++ を改善するには、コンパイラの設計と ABI を学ぶだけでなく、コンパイラについて多くの複雑なことを学ぶ必要があります。 さまざまな実行タスク形式 (ELF、PE、COFF、通常のバイナリなど) を理解し、ネイティブ Windows PE 形式 (.exe) が著作権で保護されていることを理解する必要があります。
  1. アプリケーション プログラミング インターフェイス (API) を選択します。優れた API の 1 つは、十分に文書化されている POSIX です。 すべての Unix システムは少なくとも部分的に POSIX をサポートしているため、Unix プログラムをオペレーティング システムにバンドルするのは簡単です。

    デザインを決めます。モノリシック カーネルとマイクロカーネルがあります。 モノリシック カーネルはカーネル内のすべてのサービスを実行しますが、マイクロカーネルにはサービスのカスタム実装と結合された小さなカーネルがあります。 一般に、モノリシック カーネルの方が高速ですが、マイクロカーネルの方が分離性が高く、起こり得る障害に対する保護が優れています。

    開発とチームワークを考慮してください。こうすることで、大きな問題の解決に費やす時間が短縮され、より短い時間でより優れたオペレーティング システムを作成できるようになります。

    ハードドライブを完全に消去しないでください。ディスクをフォーマットすると、すべてのデータが完全に消去されることに注意してください。 バージョンが完全に機能するまで、GRUB または別のマネージャーを使用して、別の OS からコンピューターを複製ブートします。

    小さなことから始めましょう。メモリ管理やマルチタスクなどの複雑な要素に進む前に、まずテキスト表示や中断などの小さなことに注意してください。

    最新の動作バージョンのバックアップ コピーを保管してください。これにより、OS の現在のバージョンまたはその後の追加で何か完全に問題が発生した場合に、ある程度の安心感が得られます。 あなた自身も理解しているように、コンピュータが故障して起動できなくなった場合、2 台目のコピーを用意しておくことは、既存の問題を解決できる絶好の機会となります。

    仮想マシン上で新しいオペレーティング システムをテストします。変更を加えたり、運用コンピューターからテスト コンピューターにファイルを転送したりするたびにコンピューターを再起動する代わりに、アプリケーションを使用して、現在の OS を実行し続けながら、仮想マシンで OS を実行できます。 VM アプリケーションには、VMWare (無料で利用できるサーバーもあります)、代替オープン ソース、Bochs、Microsoft Virtual PC (Linux とは互換性がありません)、および XVM VirtualBox が含まれます。

    リリースバージョンをリリースします。これにより、ユーザーはオペレーティング システムの潜在的な欠陥について知らせることができます。

  2. オペレーティング システムもユーザーフレンドリーである必要があるため、設計の不可欠な部分となる便利な機能を必ず追加してください。

    • 開発が完了したら、コードを公開するか非公開にするかを検討します。
    • システムを稼働させたい場合は、セキュリティ機能を最優先にしてください。
    • プログラミングを学ぶことを目的としてオペレーティング システム開発プロジェクトを開始しないでください。 C、C++、Pascal、またはその他の関連言語や機能 (ポインター型、低レベルのビット操作、ビット トグル、インライン アセンブラなどを含む) を知らない場合は、まだ準備ができていません。 OSを作成します。
    • OSDev や OSDever などのポータルを参照して、独自のオペレーティング システムの改善に役立ててください。 特に、OSDev.org コミュニティでは、ほとんどの問題について、フォーラムに参加するよりもサイトのコンテンツを自分で参照することを推奨していることに注意してください。 それでもフォーラムのメンバーに加わることを決めた場合、そのためには特定の前提条件が必要です。 C または C++ および x86 アセンブリ言語に関する十分な知識が必要です。 また、リンク リストやキューなど、プログラミングにおける一般的で複雑な概念も理解する必要があります。 OSDev コミュニティは、ルールの中で、誰も新人プログラマーの子守りをしないと明示しています。 OSを開発しようとしているなら、言うまでもなくプログラミングの神様です。 選択したプロセッサ アーキテクチャのプロセッサ マニュアルも読む必要があります。 たとえば、x86 (Intel)、ARM、MIPS、PPC など。 このようなプロセッサの構造に関する参考書は、Google で検索すると簡単に見つかります(「インテル マニュアル」「ARM マニュアル」など)。 明らかな質問をするために OSDev.org フォーラムに参加しないでください。 これでは単に「クソマニュアルを読んでください」というような反応が返ってきます。 まず、使用するさまざまなツールのマニュアルである Wikipedia を読んでみてください。
    • 潜在的なデッドスポットやその他のエラーがないか確認してください。 ギャップ、行き止まり、その他の問題は、オペレーティング システムの設計に影響を与える可能性があります。
    • もっと簡単な方法が必要な場合は、Fedora Revisor、Custom Nimble X、Puppy Remaster、PCLinuxOS mklivecd、SUSE Studio、SUSE KIWI などの Linux ディストリビューションを検討してください。 ただし、作成される OS は、このサービスを最初に導入した企業に属します (ただし、GPL に基づいて自由に配布、変更、実行する権利はあります)。
    • 良い解決策は、開発中のオペレーティング システム用にまったく新しいパーティションを作成することです。

    警告

    • 不用意に OS をハード ドライブにコピーすると、OS が完全に損傷する可能性があります。 気をつけて
    • 2 週間ではシステムが完全に完成することはありません。 起動可能なオペレーティング システムから始めて、より興味深いものに移ります。
    • ランダムな I/O ポートにランダムなバイトを書き込むような無謀なことをすると、OS が破壊され、(理論上は) ハードウェアが故障する可能性があります。
    • 高品質のオペレーティング システムを構築するのが簡単であるとは期待しないでください。 多くの複雑な相互依存関係があります。 たとえば、OS が複数のプロセッサを処理できるようにするには、メモリ マネージャーに、追加のプロセッサが同じリソースに同時にアクセスすることを防ぐ「ロック」メカニズムが必要です。 使用される「ブロック」にはスケジューラーが関与し、常に 1 つのプロセッサーのみが重要なリソースにアクセスし、他のすべてのプロセッサーがアイドル状態になるようにします。 ただし、スケジューラの動作はメモリ マネージャの存在に依存します。 これはデッドロック依存関係の例です。 このような問題を解決する標準的な方法はありません。 すべてのオペレーティング システム作成者には、独自のソリューションを考え出すのに十分なスキルが求められます。
トピックの続き:
りんご

通信事業者 / 2017 年 10 月 24 日 MTS 電話ファームウェア (Smart Race、Sprint、Surf、Run 4G) MTS は、他の通信事業者と同様に、顧客にさまざまなモデルのスマートフォンを提供しています。