Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OSC2021 Nagoya 「ゼロからのOS自作入門」の執筆を支える技術

「ゼロからのOS自作入門」を執筆する際に活用したOSSツールを紹介します。また、執筆中によく使ったGit Rebaseのテクニックも説明します。

  • Be the first to comment

OSC2021 Nagoya 「ゼロからのOS自作入門」の執筆を支える技術

  1. 1. 「ゼロからのOS自作入門」 の執筆を支える技術 2021年5月29日 OSC2021 Online/Nagoya @uchan_nos
  2. 2. 自己紹介 内田公太 @uchan_nos サイボウズ・ラボ株式会社でOSと言語処理系の研究開発 自作OSもくもく会コアメンバー 校正協力 執筆 執筆
  3. 3. 「ゼロからのOS自作入門」の紹介 「OS」を自分で作る過程を解説する書籍 他のOSに頼らず「Hello, world」を出力するアプリから始め、 30章で本格的なOSを作成 64ビット動作、メモリ管理、マルチタスク、ファイルシステム…… 本書で作成する「MikanOS」上で様々なアプリが動く様子
  4. 4. 執筆に使ったツール Re:VIEW 太字指定などの各種マークアップ、索引指定、PDF化 review-text-imager アスキーアートで書いた図をPNGに変換する Git MikanOSの開発にも使用 git-extract-tags 引用するソースコードをGitリポジトリから取得する もちろん、全部OSSです!
  5. 5. Re:VIEW 書籍用マークアップ言語
  6. 6. 書籍用マークアップ 書籍原稿には様々な指定が必要 太字、等幅フォント 図、表、リスト、コマンドラインの スタイル 図、表、リストの参照 章構成 執筆途中で紙面を確認したい 手軽にPDFを生成したい 書籍にはRe:VIEWがおすすめ! 書籍執筆用だけあり、必要な機能が 揃っている リストの例 ハローワールドプログラムの本体は@<tt> {Main.c}ファイルです。@<list>{day02 a_Main.c}にその全体を示します。ぱっと 見て@<chapref>{day01}で作った@<tt> {hello.c}よりすっきりしていることが分 かると思います。 Re:VIEWソースコードの例
  7. 7. Re:VIEW https://github.com/kmuto/review 書籍用のマークアップ言語+ビルドシステム Re:VIEW記法の原稿から、PDF、EPUB、HTML等に変換できる 日本人が開発の主体なので、日本語サポートがばっちり 2015年頃から開発され、最新が5.1.1 「ゼロからのOS自作入門」の原稿を書いていたころはバージョン3系 1年でメジャーバージョンが1上がるほど、開発が活発 技術書典で回を経る毎に使う人が増加していった(肌感)
  8. 8. Re:VIEW記法 「ゼロからのOS自作入門」で使った記法を一部紹介 等幅フォント @<tt>{Main.c} 画像参照 @<img>{event-propagation} 画像埋め込み //image[event-propagation][イベントの伝搬][scale=0.8]{ //} 索引登録 @<idx>{タイマ} 脚注参照 @<fn>{heavy-task} 脚注 //footnote[heavy-task][脚注本文] ユーザ定義タグも作れる  等幅フォント化+索引登録 @<codeidx>{SendMouseMessage()}
  9. 9. ラフ図案を手軽に描く
  10. 10. ラフ図案 本文を執筆中に図を入れたくなることがある その場で本格的な作図をしたくない 本格的な作図により、本文用の脳内メモリが奪われる ASCIIアートで本文中に描いて、それを図の代用としたい //image[layering][レイヤによる画面描画][scale=0.9]{ マウスのレイヤ --> -------------------- \ ---- \ デスクトップの --> - \ \ ↑ \ <---\--- マウスのウィンドウ レイヤ \ \ ---- \ \ -------------------- \ \ -------------------- //}
  11. 11. コメントを抽出してPNG化する Re:VIEWの「//image{…}」は、コメントが埋め込める →コメントを抽出してPNG化して埋め込めばいいかも? 専用ツールpngnize-image-bodyを作りました https://github.com/uchan-nos/review-text-imager 先ほどのコメントをPNG化した結果 ImageMagick + IPAゴシック でPNG生成
  12. 12. 本文でMikanOSのソースコー ドを引用する
  13. 13. 「ゼロからのOS自作入門」の特性 MikanOS自体の開発の歴史と、本文の執筆の歴史がある 本文でMikanOSのソースコードを引用する MikanOSの過去のバージョンを直したくなることがある 本文の説明をストレートにするため MikanOSの Gitリポジトリ 本文の Gitリポジトリ day01 day02 day03 コードの引用
  14. 14. 2つの歴史 MikanOSは大規模なソフトウェア →専用のリポジトリが欲しい https://github.com/uchan-nos/mikanos 本文も大規模になるので、バージョン管理したい https://github.com/uchan-nos/legacy-free-os-book MikanOSの実装を進めつつ本文を執筆 2つのGitリポジトリが、並行に進展
  15. 15. MikanOSのソースコードを引用する MikanOSのソースコードを解説するために、本文に引用したい 手動でコピペするとミスが出る Re:VIEWのファイル埋め込み機能が使えそう! #@mapfile(ファイル名)~#@end と書くと、そのファイルの内容を展開してくれる //list[list_tag][リストタイトル]{ #@mapfile(foo.c) #@end //} プリプロセッサが ソースコード を展開する
  16. 16. masterブランチから引用する? 問題:最新版のソースコードを引用するので大丈夫? 答え:ダメ。章ごとに機能を追加していくから。 特定のバージョンを引用したい //list[main][MikanOSのメイン関数]{ #@mapfile(../mikanos/kernel/main.cpp) #@end //} MikanOSの Gitリポジトリ day03 master day04 引用するバージョンを固定したい タグ ブランチ
  17. 17. main.cppの内容の変遷 extern "C" void KernelMain() { while (1) __asm__("hlt"); } osbook_day03aのmain.cpp #include <cstdint> extern "C" void KernelMain(uint64_t frame_buffer_base, uint64_t frame_buffer_size) { uint8_t* frame_buffer = reinterpret_cast<uint8_t*>(frame_buffer_base); for (uint64_t i = 0; i < frame_buffer_size; ++i) { frame_buffer[i] = i % 256; } while (1) __asm__("hlt"); } osbook_day03cのmain.cpp タグXのmain.cppを引用する main.cppを引用する
  18. 18. タグを指定して引用したい タグ毎にファイルを配置したディレクトリを用意すればできる 実際に、こんなディレクトリ構成にしてみた text/ images/ dayN.re … distrib/ dayN/ MikanLoaderPkg/Main.c kernel/main.cpp … …
  19. 19. タグを指定して引用する タグ毎にファイルを配置したディレクトリを用意すればできる 実際に、こんなディレクトリ構成にしてみた text/ images/ dayN.re … distrib/ dayN/ MikanLoaderPkg/Main.c kernel/main.cpp … … 希望のタグから ソースコードを引用する osbook_dayN タグに対応
  20. 20. タグを指定して引用する //list[day02a_Main.c][EDK IIを使ったハローワールドアプリ(Main.c)][c]{ #@mapfile(../distrib/day02a/MikanLoaderPkg/Main.c) #include <Uefi.h> #include <Library/UefiLib.h> EFI_STATUS EFIAPI UefiMain( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) { Print(L"Hello, Mikan World!n"); while (1); return EFI_SUCCESS; } #@end //} ハローワールドプログラムの本体は@<tt>{Main.c}ファイルです。 @<list>{day02a_Main.c}にその全体を示します。 Re:VIEWを使った本文の例
  21. 21. タグ内容を抽出するツール osbook_dayNというタグに対応するソースコードを取得し distrib/dayNディレクトリに展開したい 専用ツールgit-extract-tagsを作りました https://github.com/uchan-nos/git-extract-tags 使い方 $ git extract-tags -s distrib osbook_ ../mikanos プレフィクスが「osbook_」であるタグから ファイルを抽出してdistribに書き出す legacy-free-os-book/ text/ images/ dayN.re … distrib/ dayN/ … mikanos/ MikanLoaderPkg/ kernel/ … 想定するディレクトリ構成
  22. 22. MikanOSの過去のバージョン を直したくなることがある
  23. 23. ソフトウェアにはバグがある 執筆中にOSのバグを見つけることがよくある 解説文を書いていると、コードの動作を深く考えるから、余計に。 osbook_day06cでバグを入れてしまったことに 第20章を執筆中に気付くと、大変辛い。 6c、20という数字はただの例。後で見つかれば見つかるほど辛い 選択肢1:第20章に「osbook_day06cの実装にバグがあったので、 直します」みたいな解説文を書き、osbook_day20xを修正する 選択肢2:osbook_day06cに修正を加え、何事も無かったかのよう に執筆を進める
  24. 24. MikanOSの歴史を綺麗に保つ やはり「選択肢2」を取りたい 選択肢1の方がリアルな開発姿勢だが、解説がごちゃごちゃする ただでさえ大変なOS自作なので、解説くらいは綺麗にしたい Gitで過去のバージョンを修正するには? →リベース! MikanOSの Gitリポジトリ 本文の Gitリポジトリ day06b day06c master … … master
  25. 25. リベース A B C day06b D day06c master X … a バグ修正コミット リベース:Cのベースをaに付け替える A B C day06b D day06c master X … a … C’ D’ X’ 1. バグ修正を コミットする 2. リベースする
  26. 26. リベースの問題点 MikanOSの利用者が困惑する 公開されたブランチをリベースするのは混乱の元 MikanOSでは、しばらくはリベースがたくさん発生するよ、とREADME に書いた タグが付け変わらない day06cがCを指したまま C’を指して欲しい タグを手動で付け替えるのは大変 BからXまでの、全タグを付け替える必要あり リベース作業はバグ発見のたびに何度も発生 B C D day06c master X … a … C’ D’ X’
  27. 27. タグを付け替えるツール 元のブランチからリベース先のブランチへ各タグを移動したい 専用ツールgit-retagを作りました https://github.com/uchan-nos/git-extract-tags 使い方 $ git retag osbook_ old new プレフィクスが「osbook_」であるタグを、oldからnewへ付け替える A B C tag1 new E a B’ C’ E’ old D D’ tag2
  28. 28. タグ付け替えの例 「handle close button」と「exit task on window close」の間に修 正を挿入する例  挿入した修正「hoge-fix」 「osbook_dayX」というタグす べてを、「new-day30f」ブラン チに移動したい
  29. 29. git-retag使用例 git retag --dry-run osbook_ osbook_day30f new-day30f 指定した2つのブラン チの共通の祖先を見つ け、 プレフィクスが 「osbook_」であるタ グを移動する
  30. 30. Git rebase入門
  31. 31. コミットグラフを理解しよう リベース操作は複雑で分かりにくい? コミットグラフの変化が想像できるようになれば、怖くない! コミット:ワークツリー全体のスナップショット  Diffではない ブランチ:コミットを指すラベル  コミットの列、ではない A B C D master コミット ブランチ
  32. 32. コミットはDiffではない コミットは、親に対する差分、ではない コミットは、ワークツリー全体のスナップショットである 1つのコミットは、管理対象の全ファイルの完全な内容を持つ もちろん、無変更のファイルの内容は持たない、などの最適化はある Diffではないので、自由に組み替え可能 A B C
  33. 33. リベース A B C D master a $ git checkout -b fix-bug B 《ワークツリーを修正》 $ git commit -a $ git rebase fix-bug master fix-bug A B master a fix-bug C’ D’
  34. 34. リベース(interactiveモード) 非常に多用途な git rebase -i コミットの順番を入れ替える、 不要なコミットを捨てる、 コミットメッセージを修正する、など A B C D master ここを入れ替えたいなあ…… $ git checkout master $ git rebase -i A 行を入れ替えて保存
  35. 35. git rebase -iのその他の機能 # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # # These lines can be re-ordered; they are executed from top to bottom. 「pick」を希望のコマンドに書き換える
  36. 36. コミットグラフを理解する便利なコマンド $ git log --graph --all ここで枝分かれして ここでマージされた
  37. 37. 間違ったリベースを無かったことにする Git reflog 「ブランチやタグ等が、過去何を指していたか」が コミットやリベース等、Gitの操作をするたびに記録される リベースなどでミスしてもデータが失われるわけではないので、 安心して実験しましょう ブランチを任意のコミットに付け直すには $ git checkout <branch> $ git reset --hard <commit>
  38. 38. まとめ 「ゼロからのOS自作入門」の執筆に様々なOSSを使った Re:VIEW、review-text-imager、Git、git-extract-tags ラフ図案をASCIIアートで→pngnize-image-body 「ゼロからのOS自作入門」は2本のGitリポジトリで構成される タグを指定したソースコード引用を行いたい→git-extract-tags 引用プログラムのバグを直したい→git-retag リベースを使いこなそう

×