├── .gitignore ├── EDITOR_GUIDE.md ├── Gemfile ├── LICENSE ├── README.md ├── _includes └── breadcrumbs.html ├── _layouts └── default.html ├── browser ├── cover.png ├── errata.md └── index.md ├── errata.md └── os1 ├── cover.png ├── errata.md └── index.md /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore is appropriate for repositories deployed to GitHub Pages and using 2 | # a Gemfile as specified at https://github.com/github/pages-gem#conventional 3 | 4 | # Basic Jekyll gitignores (synchronize to Jekyll.gitignore) 5 | _site/ 6 | .sass-cache/ 7 | .jekyll-cache/ 8 | .jekyll-metadata 9 | 10 | # Additional Ruby/bundler ignore for when you run: bundle install 11 | /vendor 12 | 13 | # Specific ignore for GitHub Pages 14 | # GitHub Pages will always use its own deployed version of pages-gem 15 | # This means GitHub Pages will NOT use your Gemfile.lock and therefore it is 16 | # counterproductive to check this file into the repository. 17 | # Details at https://github.com/github/pages-gem/issues/768 18 | Gemfile.lock 19 | -------------------------------------------------------------------------------- /EDITOR_GUIDE.md: -------------------------------------------------------------------------------- 1 | ``` 2 | sudo apt-get install ruby-full 3 | gem install bundler 4 | bundle install 5 | bundle exec jekyll serve 6 | ``` 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # gem "jekyll" 6 | gem "github-pages", "~> 232", group: :jekyll_plugins 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 hikalium 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Wasabi サポートページ](https://lowlayergirls.github.io/wasabi-help/) へようこそ! 2 | 3 | [ 4 | 5 | 「[作って学ぶ] ブラウザのしくみ」 6 | サポートページはこちら 7 | ](./browser/) 8 | 9 | ---- 10 | 11 | [ 12 | 13 | 「[作って学ぶ] OSのしくみI」 14 | サポートページはこちら 15 | ](./os1) 16 | -------------------------------------------------------------------------------- /_includes/breadcrumbs.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% seo %} 9 | 10 | {% include head-custom.html %} 11 | 12 | 13 |
14 | {% include breadcrumbs.html %} 15 | {% if site.title and site.title != page.title and false %} 16 |

{{ site.title }}

17 | {% endif %} 18 | 19 | {{ content }} 20 | 21 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /browser/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlayergirls/wasabi-help/11a0e8659504d903562eb13d92722969db5aa89f/browser/cover.png -------------------------------------------------------------------------------- /browser/errata.md: -------------------------------------------------------------------------------- 1 | - Table of Content 2 | {:toc} 3 | 4 | # 正誤表(最終更新日:2025/04/23) 5 | 6 | 本書に下記のとおり誤りがございました。お詫びして訂正いたします。 7 | 8 | # 初版第1刷をお持ちの方(第2刷で修正済み) 9 | 10 | ## p.vii 「アプリケーションをWasabiOSで動かす」1段落目 11 | 12 | - 誤: 13 | 14 | アプリケーションをWasabiOSで動かすためには、cargo buildコマンドでビルドしたアプリケーションのバイナリを、WasabiOSが提供するrun_with_app.shというスクリプトを使用して走らせる必要があります。これらを自動的に行ってくれる便利なシェルスクリプトを用意したので、以下のスクリプトを自分のプロジェクトに追加してください。または、d0iasm/saba/run_on_wasabi.shからコピーすることもできます。 15 | 16 | - 正: 17 | 18 | アプリケーションをWasabiOSで**動かすには**、cargo buildコマンドでビルドしたアプリケーションのバイナリを、WasabiOSが提供するrun_with_app.shというスクリプトを使用して走らせる必要があります。これらを自動的に**行う**シェルスクリプトを用意したので、以下のスクリプトを**後ほどcargoコマンドによって作成するプロジェクトのトップディレクトリに追加してください。d0iasm/saba/run_on_wasabi.shからコピーもできます。** 19 | 20 | ## p.viii 1つ目のリスト下から6行目 21 | 22 | - 誤:wget https://raw.githubusercontent.com/hikalium/wasabi/main/external_app_template/ 23 | - 正:wget https://raw.githubusercontent.com/hikalium/wasabi/**for_saba**/external_app_template/**↵** 24 | 25 | ## p.viii 3段落1行目 26 | 27 | - 誤: 28 | 29 | また、もしスクリプトが途中で失敗したら、rm -rf buildなどによりダウンロードしたWasabiOSのソースコードを削除してみてください。 30 | 31 | - 正: 32 | 33 | **もし**スクリプトが途中で失敗したら、rm -rf buildなど**で**ダウンロードしたWasabiOSのソースコードを**削除してください**。**環境によってはwgetの導入が必要です。** 34 | 35 | ## p.ix 4段落1行目 36 | 37 | - 誤:スクリプトを走らせると、QEMUのアプリケーションが開始します(図0-1)。 38 | - 正:**スクリプト**を走らせると、QEMUのアプリケーション**上でOS**が開始します(図0-1)。 39 | 40 | ## p.28 「ストレージ」1段落5行目 41 | 42 | - 誤:少なくとも合計で3,000個までのCookieを保存 43 | - 正:少なくとも合計で3,000個**の**Cookieを保存 44 | 45 | ## p.48 「スキームの確認」2つ目のリスト上から3行目 46 | 47 | - 誤:fn is_http(&mut self) -> bool { 48 | - 正:fn is_http(**&self**) -> bool { 49 | 50 | ## p.57 1つ目のリスト7行目 51 | - 誤:let url = "http://example.com:8888/index.html?a=123&b= 456".to_string(); 52 | - 正:let url = "http://example.com:8888/index.html?a=123&**b=456**".to_string(); 53 | 54 | 「3&b= 456」の半角スペースを削除 55 | 56 | ## p.75 2つ目のリスト3行目 57 | - 誤:use crate::alloc::string::ToString; 58 | - 正:use **alloc**::string::ToString; 59 | 60 | ## p.77 2行目 61 | - 誤:コネクション確率 62 | - 正:コネクション**確立** 63 | 64 | ## p.84 「文字列の前処理」2段落3行目 65 | - 誤:改行シーケンス(\n\r) 66 | - 正:改行シーケンス(**\r\n**) 67 | 68 | ## p.84 「文字列の前処理」2段落4行目 69 | - 誤:\n\rはWindows 70 | - 正:**\r\n**はWindows 71 | 72 | ## p.84 2つ目のリスト5行目 73 | - 誤:raw_response.trim_start().replace("\n\r", "\n"); 74 | - 正:raw_response.trim_start().replace("**\r\n**", "\n"); 75 | 76 | ## p.84 3つ目のリスト5行目 77 | - 誤:raw_response.trim_start().replace("\n\r", "\n"); 78 | - 正:raw_response.trim_start().replace("**\r\n**", "\n"); 79 | 80 | ## p.126 「AttributeValueUnquoted状態の実装」1段落1行目 81 | - 誤:シングルクオートで囲まれたタグ 82 | - 正:**クオート**で囲まれ**ていない**タグ 83 | 84 | ## p.130 1つ目のリスト3行目 85 | - 誤:either↵StartTag 86 | - 正:either StartTag 87 | 88 | 間の矢印を削除し半角スペースに 89 | 90 | ## p.134 1つ目のコマンド1行目 91 | - 誤:$ mv saba_core 92 | - 正:$ **cd** saba_core 93 | 94 | ## p.188 1つ目のコマンド1行目 95 | - 誤:$ mv saba_core 96 | - 正:$ **cd** saba_core 97 | 98 | ## p.215 1つ目のリスト10行目 99 | - 誤:(self.consume_numeric_token()); 100 | - 正:(self.consume_numeric_t**oken());** 101 | 102 | 「oken());」の部分を太字に 103 | 104 | ## p.216 1つ目のリスト5行目 105 | - 誤:floating_digit 106 | - 正:f**loating_digit** 107 | 108 | 「loating_digit」の部分を太字に 109 | 110 | ## p.216 1つ目のリスト7行目 111 | - 誤:c.to_digit(10).unwrap() as f64 112 | - 正:c.to_digit(10).unwrap() **as f64** 113 | 114 | 「as f64」の部分を太字に 115 | 116 | ## p.241 1つ目のコマンド7,8行目 117 | - 誤: 118 | 119 | ``` 120 | ├── layout_object.rs 121 | ├── layout_point.rs 122 | ├── layout_size.rs 123 | └── layout_view.rs 124 | ``` 125 | 126 | - 正: 127 | 128 | ``` 129 | ├── layout_object.rs 130 | └── layout_view.rs 131 | ``` 132 | 133 | ## p.438 「ローカルサーバの構築」2段落1行目 134 | - 誤:OSを起動させたあと、 135 | - 正:OSを起動させ**、sabaと入力しアプリケーションを開始した**あと、 136 | 137 | # 初版第1~2刷をお持ちの方(第3刷で修正済み) 138 | 139 | ## p90 「メイン関数の実装」リスト下から1行目 140 | - 誤:match client.get("example.com".to_string(), 80, "/".to_string()) { 141 | - 正:match client.get("example.com".to_string(), 80, **""**.to_string()) { ◀「"/"」の「/」を削除 142 | 143 | ## p94 「メイン関数の変更」リスト5行目 144 | - 誤:match client.get("host.test".to_string(), 8000, "/test.html".to_string()) { 145 | - 正:match client.get("host.test".to_string(), 8000, "**test.html**".to_string()) { 146 | 147 | ## p127 「AfterAttributeValueQuoted 状態の実装」2段落7行目 148 | - 誤:BeforeAttributeValue 状態に移動します。 149 | - 正:BeforeAttribute**Name**状態に移動します。 150 | 151 | ## p128 リスト下から7行目 152 | - 誤:self.state = State::BeforeAttributeValue; 153 | - 正:self.state = State::BeforeAttribute**Name**; 154 | 155 | ## p166 「要素ノードの追加」2段落2行目 156 | - 誤:ノード(current)呼ぶ 157 | - 正:るノード(current)**と**呼ぶ 158 | 159 | ## p167 リスト 160 | 161 | - 誤: 162 | 163 | ``` 164 | if current.borrow().first_child().is_some() { ── ❹ 165 | let mut last_sibiling = current.borrow().first_child(); 166 | loop { ── ❺ 167 | last_sibiling = match last_sibiling { 168 | Some(ref node) => { 169 | if node.borrow().next_sibling().is_some() { 170 | node.borrow().next_sibling() 171 | } else { 172 | break; 173 | } 174 | } 175 | None => unimplemented!("last_sibiling should be Some"), 176 | }; 177 | } 178 | 179 | last_sibiling 180 | .unwrap() 181 | .borrow_mut() 182 | .set_next_sibling(Some(node.clone())); ── ❻ 183 | node.borrow_mut().set_previous_sibling(Rc::downgrade( 184 | ¤t 185 | .borrow() 186 | .first_child() 187 | .expect("failed to get a first child"), 188 | )) 189 | } else { ── ❼ 190 | current.borrow_mut().set_first_child(Some(node.clone())); ── ❽ 191 | } 192 | 193 | current.borrow_mut().set_last_child(Rc::downgrade(&node)); ── ❾ 194 | node.borrow_mut().set_parent(Rc::downgrade(¤t)); ── ❿ 195 | 196 | self.stack_of_open_elements.push(node); ── ⓫ 197 | } 198 | } 199 | ``` 200 | 201 | - 正: 202 | 203 | ``` 204 | if current.borrow().first_child().is_some() { ── ❹ 205 | let mut last_sibling = current.borrow().first_child(); ◀「sibling」のスペルを修正 206 | loop { ── ❺ 207 | last_sibling = match last_sibling { ◀「sibling」のスペルを修正 208 | Some(ref node) => { 209 | if node.borrow().next_sibling().is_some() { 210 | node.borrow().next_sibling() 211 | } else { 212 | break; 213 | } 214 | } 215 | None => unimplemented!("last_sibling should be Some"), ◀「sibling」のスペルを修正 216 | }; 217 | } 218 | 219 | last_sibling ◀「sibling」のスペルを修正 220 | .as_ref() ◀追加 221 | .unwrap() 222 | .borrow_mut() 223 | .set_next_sibling(Some(node.clone())); ── ❻ 224 | node.borrow_mut().set_previous_sibling(Rc::downgrade( 225 | &last_sibling.expect("last_sibling should be Some") ◀変更 226 | )) 227 | } else { ── ❼ 228 | current.borrow_mut().set_first_child(Some(node.clone())); ── ❽ 229 | } 230 | 231 | current.borrow_mut().set_last_child(Rc::downgrade(&node)); ── ❾ 232 | node.borrow_mut().set_parent(Rc::downgrade(¤t)); ── ❿ 233 | 234 | self.stack_of_open_elements.push(node); ── ⓫ 235 | } 236 | } 237 | ``` 238 | 239 | ## p171 リストの19行目 240 | 241 | - 誤: 242 | 243 | ``` 244 | if current.borrow().first_child().is_some() { ── ❺ 245 | current 246 | .borrow() 247 | .first_child() 248 | .unwrap() 249 | .borrow_mut() 250 | .set_next_sibling(Some(node.clone())); ── ❻ 251 | node.borrow_mut().set_previous_sibling(Rc::downgrade( 252 | ¤t 253 | .borrow() 254 | .first_child() 255 | .expect("failed to get a first child"), 256 | )); 257 | ``` 258 | 259 | - 正: 260 | 261 | ``` 262 | if current.borrow().first_child().is_some() { ── ❺ 263 | current 264 | .borrow() 265 | .first_child() 266 | .unwrap() 267 | .borrow_mut() 268 | .set_next_sibling(Some(node.clone())); ── ❻ 269 | ◀削除 270 | ``` 271 | 272 | ## p273 「位置の計算」2段落3、4、5行目 273 | - 誤:sibiling 274 | - 正:**sibling** 275 | 276 | ## p273-274 リスト5、6、7、12、13、14行目 277 | - 誤:sibiling 278 | - 正:**sibling** 279 | 280 | ## p275 リスト5、6、7、11、14、15、24、25行目 281 | - 誤:sibiling 282 | - 正:**sibling** 283 | 284 | ## p334 リスト下から7行目 285 | - 誤:return Err(Error::InvalidUI("failed to draw a string".to_string())); 286 | - 正:return Err(Error::InvalidUI("failed to draw a **rect**".to_string())); 287 | 288 | ## p379 リスト1行目 289 | 290 | - 誤: 291 | 292 | ``` 293 | if self.input[self.pos].is_ascii_alphanumeric() || self.input[self.pos] == '$' { 294 | ``` 295 | 296 | 297 | - 正: 298 | 299 | ``` 300 | if self.input[self.pos].is_ascii_alphanumeric() 301 | || self.input[s elf.pos] == '_' || self.input[self.pos] == '$' { ◀「|| self.input[s elf.pos] == '_'」を追加 302 | ``` 303 | 304 | ## p384 1つ目のリスト10行目 305 | 306 | - 誤: ::= (& | _ | a-z | A-Z) (& | a-z | A-Z)* 307 | - 正: ::= ($ | _ | a-z | A-Z)+ ◀「$」「+」に変更 308 | 309 | ## p394 「変数の取得」1段落1行目 310 | 311 | - 誤:Environment 構造体に保存されている変数をまずvariablesに保存されている変数をチェックし 312 | - 正:Environment 構造体**の**variablesに保存されている変数をチェックし 313 | 314 | ## p394 「変数の追加と更新」1段落1行目、2段落1行目 315 | 316 | - 誤:varialbe 317 | - 正:vari**able** 318 | 319 | ## p395 「evalメソッドの変更」3段落3行目、6段落1行目 320 | 321 | - 誤:varialbe 322 | - 正:vari**able** 323 | 324 | ## p405 上から3行目 325 | 326 | - 誤:変名 327 | - 正:変**数**名 328 | 329 | ## p426 「ブラウザAPIを呼び出すメソッドの追加」4段落4行目 330 | 331 | - 誤:取得ための 332 | - 正:取得**する**ための 333 | 334 | # 初版第1~3刷をお持ちの方 335 | 336 | ## p379 リスト上から2行目 337 | 338 | - 誤:`|| self.input[s elf.pos] == '_' || self.input[self.pos] == '$' {` 339 | - 正:`|| self.input[self.pos] == '_' || self.input[self.pos] == '$' {` ◀「s elf」から半角スペースを削除 340 | -------------------------------------------------------------------------------- /browser/index.md: -------------------------------------------------------------------------------- 1 | # 「作って学ぶ ブラウザのしくみ」サポートページ 2 | このページは、[土井麻未(d0iasm) 著 「作って学ぶ ブラウザのしくみ」(技術評論社, 2024)](https://gihyo.jp/book/2024/978-4-297-14546-0)の内容を補完する情報を掲載しています。 3 | 4 | 本ページや上記書籍についてのフィードバックは、[本サポートサイトの GitHub Issues](https://github.com/lowlayergirls/wasabi-help/issues)経由で著者までお知らせください。 5 | 6 | ハッシュタグは [#作って学ぶブラウザのしくみ](https://x.com/search?q=%23%E4%BD%9C%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF&src=typed_query&f=live) です。 7 | 8 | 9 | 10 | ## 関連リンク 11 | 12 | - 13 | - 14 | 15 | # 正誤情報 16 | 17 | [『[作って学ぶ]ブラウザのしくみ』正誤表](./errata) 18 | 19 | # 補足情報 20 | 21 | ## wgetがみつからない 22 | 23 | 原因: wgetコマンドがインストールされていない。(macOS等) 24 | 25 | 解決策: wgetコマンドをHomebrew等のパッケージマネージャ経由でインストールするか、`wget`を`curl -O`(curlのあとに半角スペース、続いてハイフンと大文字アルファベットO)に置き換えて実行してみてください。 26 | 27 | ## (コード修正済)`the x86_64-unknown-none target may not be installed` 28 | 29 | **(2024-11-11)[Makefileの変更](https://github.com/hikalium/wasabi/commit/4796f62364ce8f24613dccba60618e1d35254b16)により修正しました。** 30 | **`run_on_wasabi.sh`によって自動的にダウンロードしたMakefileを削除し、もう一度`run_on_wasabi.sh`スクリプトを走らせると問題は出なくなっているはずです。** 31 | 32 | 症状: 以下のようなエラーが`./run_on_wasabi.sh`を実行した際に発生し、失敗する。 33 | 34 | ``` 35 | error[E0463]: can't find crate for `core` 36 | | 37 | = note: the `x86_64-unknown-none` target may not be installed 38 | = help: consider downloading the target with `rustup target add x86_64-unknown-none` 39 | 40 | For more information about this error, try `rustc --explain E0463`. 41 | error: could not compile `sabi` (lib) due to 1 previous error 42 | ``` 43 | 44 | 解決策: 以下のコマンドを実行してから再度試してみてください。 45 | ``` 46 | rustup target add x86_64-unknown-none 47 | ``` 48 | 49 | それでもだめな場合は、cargoがパスに正しく登録されていない可能性があります。rustupのインストールをやり直すか、パスを手動で追加して実行してみてください。 50 | ``` 51 | export PATH="$HOME/.cargo/bin:$PATH" 52 | rustup target add x86_64-unknown-none 53 | ``` 54 | 55 | #### Reference 56 | 57 | - 58 | 59 | ## (コード修正済)環境構築のHello, Worldで、"No route" "Timed out"という WARN が出ている 60 | 61 | **(2024-11-11)[OS側のログ出力の変更](https://github.com/hikalium/wasabi/commit/abf27c6f587e777fce5c53234d45d997ed075996)により修正しました。** 62 | 63 | これはOS側のコード由来のWarningなので、無視して大丈夫です。 64 | 65 | エラーを無視して自作OS上で`saba`と実行すれば、Hello, worldが表示されます。 66 | 67 | ## run_on_wasabi.shを実行してもQEMUが起動しない 68 | 69 | ``` 70 | export DISPLAY=0 71 | ``` 72 | 73 | を実行してから再度試してみてください。OS側ビルドスクリプトでの修正を予定しています。 74 | 75 | #### Reference 76 | 77 | - 78 | 79 | ## net/wasabi/src/http.rsでcrate::alloc::string::ToStringが見つからない 80 | 81 | `net/wasabi/src/http.rs`で`ToString`モジュールをインポートする際、unresolved importのエラーになってしまう。 82 | 83 | ``` 84 | error[E0433]: failed to resolve: unresolved import 85 | --> net/wasabi/src/http.rs:4:12 86 | | 87 | 4 | use crate::alloc::string::ToString; 88 | | ^^^^^ 89 | | | 90 | | unresolved import 91 | | help: a similar path exists: `core::alloc` 92 | ``` 93 | 94 | [リファレンスコード](https://github.com/d0iasm/sababook/blob/main/ch3/saba/net/wasabi/src/http.rs)にあるように、`crate`をつけずに`use alloc::string::ToString`としてください。 95 | 96 | 書籍のコードは次の版で修正予定です。 97 | 98 | #### Reference 99 | 100 | - 101 | 102 | ## 関連書『[作って学ぶ]OSのしくみ』の出版予定 103 | 104 | 『[作って学ぶ]ブラウザのしくみ』の中で関連書として紹介している『[作って学ぶ]OSのしくみ』は、2025年の刊行を予定しております。刊行まで、もうしばらくお待ち下さい。 105 | 106 | なお、OS部分のソースコードについては、機能的に同等なものを[こちら](https://github.com/hikalium/wasabi)から読むことができます。 107 | -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | [ 2 | 3 | 「[作って学ぶ] ブラウザのしくみ」 4 | 正誤表はこちら 5 | ](./browser/errata) 6 | 7 | ---- 8 | 9 | [ 10 | 11 | 「[作って学ぶ] OSのしくみI」 12 | 正誤表はこちら 13 | ](./os1/errata) 14 | -------------------------------------------------------------------------------- /os1/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlayergirls/wasabi-help/11a0e8659504d903562eb13d92722969db5aa89f/os1/cover.png -------------------------------------------------------------------------------- /os1/errata.md: -------------------------------------------------------------------------------- 1 | - Table of Content 2 | {:toc} 3 | 4 | # 正誤表(最終更新日:2025/05/03) 5 | 6 | 本書に下記のとおり誤りがございました。お詫びして訂正いたします。 7 | 8 | # 初版第1刷の正誤表 9 | 10 | ## p.xv「第4章 マルチタスクを実装しよう」目次要素 11 | 12 | - 誤: 13 | 14 | aync/awaitを使えるようにする 15 | 16 | - 正: 17 | 18 | async/awaitを使えるようにする 19 | 20 | ## p.48「"Hello, world"はどこへ行く?」2段落目 21 | 22 | - 誤: 23 | 24 |  鍵となるのは、この`prinln!`です。 25 | 26 | - 正: 27 | 28 |  鍵となるのは、この`println!`です。 29 | 30 | 31 | ## p.161「OSのテストをRustで書く」3段落2行目 32 | 33 | - 誤: 34 | 35 | うまくいったら正常に終了し、そうでなければ`panic()`するような関数を書けばよいです。 36 | 37 | - 正: 38 | 39 | うまくいったら正常に終了し、そうでなければ`panic!()`するような関数を書けばよいです。 40 | 41 | ## p.161「OSのテストをRustで書く」3段落4行目 42 | 43 | - 誤: 44 | 45 | もし想定と違えば`panic()`するような 46 | 47 | - 正: 48 | 49 | もし想定と違えば`panic!()`するような 50 | 51 | ## p.162「シリアルポート出力の実装」4段落目 52 | 53 | - 誤: 54 | 55 | 今回はエミューレーターを使用して 56 | 57 | - 正: 58 | 59 | 今回はエミュレーターを使用して 60 | 61 | ## p.167 サンプルコード`src/allocator.rs`内 62 | 63 | - 誤: 64 | 65 | ``` 66 | assert_eq!(round_up_to_nearest_pow2(9), Ok(16)); 67 | assert_eq!(round_up_to_nearest_pow2(9), Ok(16)); 68 | ``` 69 | 70 | - 正: 71 | 72 | ``` 73 | assert_eq!(round_up_to_nearest_pow2(9), Ok(16)); 74 | 75 | ``` 76 | 77 | (注: 78 | テストケースの最後の2つが冗長でしたので片方を削除しました。残っていても間違いではありませんが、削除したほうがより適切です。) 79 | 80 | ## p.188 コードブロック内 81 | 82 | 最上部のコードブロックと、ページ中央のコードブロックの2箇所について: 83 | 84 | - 誤: 85 | 86 | ``` 87 | 0x0XAC_TUWP 88 | ``` 89 | 90 | - 正: 91 | 92 | ``` 93 | 0b0XAC_TUWP 94 | ``` 95 | 96 | ## p.194 「async/awaitを使えるようにする」4段落目 97 | 98 | - 誤: 99 | 100 | _Identity mapping_ 101 | 102 | - 正: 103 | 104 | _Identity Mapping_ 105 | 106 | ## p.204 サンプルコード`src/x86.rs`内 107 | 108 | - 誤: 109 | 110 | ``` 111 | struct FPUContenxt { 112 | ``` 113 | 114 | - 正: 115 | 116 | ``` 117 | struct FPUContext { 118 | ``` 119 | 120 | ## p.205 サンプルコード`src/x86.rs`内 121 | 122 | - 誤: 123 | 124 | ``` 125 | fpu_context: FPUContenxt, // used by FXSAVE / FXRSTOR 126 | ``` 127 | 128 | - 正: 129 | 130 | ``` 131 | fpu_context: FPUContext, // used by FXSAVE / FXRSTOR 132 | ``` 133 | 134 | ## p.214 サンプルコード`src/x86.rs`内 135 | 136 | - 誤: 137 | 138 | ``` 139 | pub const BIT_CS_READABLE: u64 = 1u64 << 53; 140 | ``` 141 | 142 | - 正: 143 | 144 | ``` 145 | pub const BIT_CS_READABLE: u64 = 1u64 << 41; 146 | ``` 147 | 148 | ## p.219 サンプルコード`src/uefi.rs`内 149 | 150 | - 誤: 151 | 152 | ``` 153 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] 154 | #[must_use] 155 | #[repr(u64)] 156 | descriptor_size: *mut usize, 157 | descriptor_version: *mut u32, 158 | ) -> EfiStatus, 159 | ``` 160 | 161 | - 正: 162 | 163 | ``` 164 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] 165 | #[must_use] 166 | #[repr(u64)] 167 | 168 | // << 中略 >> 169 | 170 | pub struct EfiBootServicesTable { 171 | // << 中略 >> 172 | descriptor_size: *mut usize, 173 | descriptor_version: *mut u32, 174 | ) -> EfiStatus, 175 | ``` 176 | 177 | ## p.220 サンプルコード内 `locate_loaded_image_protocol()`関数内 178 | 179 | ここでは`graphic_output_protocol`という名前の変数が宣言・使用されていますが、実際には`loaded_image_protocol`に相当する値を格納する変数となっています。したがって、これに即した変数名とするのがより適切でした。プログラム自体の動作には影響ありませんが、混乱を招いたことをお詫びいたします。 180 | 181 | ## p.224 サンプルコード`src/init.rs`内 182 | 183 | - 誤: 184 | 185 | ``` 186 | pub fn init_basic_runtime( 187 | image_handle: EfiHandle, 188 | ALLOCATOR.init_with_mmap(&memory_map); 189 | memory_map 190 | } 191 | ``` 192 | 193 | - 正: 194 | 195 | ``` 196 | pub fn init_basic_runtime( 197 | image_handle: EfiHandle, 198 | 199 | // << 中略 >> 200 | 201 | ALLOCATOR.init_with_mmap(&memory_map); 202 | memory_map 203 | } 204 | ``` 205 | 206 | ## p.245 「async/awaitを使えるようにする」見出し 207 | 208 | - 誤: 209 | 210 | aync/awaitを使えるようにする 211 | 212 | - 正: 213 | 214 | async/awaitを使えるようにする 215 | 216 | ## p.311「ECAM ―― Enhanced Configuration Access Method」3段落目 217 | 218 | - 誤: 219 | 220 | 各デバイスに対応するConfiguration間 221 | 222 | - 正: 223 | 224 | 各デバイスに対応するConfiguration空間 225 | 226 | ## p.312 ページ一番下のコマンド出力結果について 227 | 228 | - 誤: 229 | 230 | ``` 231 | $ qemu-system-x86_64 -machine ? | grep q35 | head -n 1 232 | ``` 233 | 234 | - 正: 235 | 236 | ``` 237 | $ qemu-system-x86_64 -machine '?' | grep q35 | head -n 1 238 | ``` 239 | -------------------------------------------------------------------------------- /os1/index.md: -------------------------------------------------------------------------------- 1 | # 「作って学ぶ OSのしくみ(I)」サポートページ 2 | このページは、[hikalium 著 「作って学ぶ OSのしくみ(I)」(技術評論社, 2025)](https://gihyo.jp/book/2025/978-4-297-14859-1)の内容を補完する情報を掲載しています。 3 | 4 | 本ページや上記書籍についてのフィードバックは、[本サポートサイトの GitHub Issues](https://github.com/lowlayergirls/wasabi-help/issues)経由で著者までお知らせください。 5 | 6 | ハッシュタグは [#OSのしくみ](https://x.com/search?q=%23OS%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF%20OR%20%E4%BD%9C%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6OS%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF&src=typed_query&f=live) です。 7 | 8 | 9 | 10 | ## 関連リンク 11 | 12 | - 13 | - 14 | 15 | # 正誤情報 16 | 17 | [『[作って学ぶ]OSのしくみ』正誤表](./errata) 18 | 19 | # 補足情報 20 | 21 | ## `rust-analyzer`の設定について 22 | 23 | Rustのコードを書く際には`rust-analyzer`というLSPサーバーが非常に便利です。筆者もいつも大変お世話になっています。 24 | しかし、本書のリポジトリで`rust-analyzer`がうまく動作しない場合があるようですので、その解決策をご紹介します。 25 | 26 | 本書のリポジトリでは再現性を確保するため、Rustツールチェインのバージョンを`rust-toolchain.toml`に記載のとおり固定しています。そのため、より新しいバージョンのRustツールチェインに同梱されている`rust-analyzer`を使用すると、エラーが発生する可能性があります。多くのエディタにおいて`rust-analyzer`拡張機能は、`rust-toolchain.toml`の内容にかかわらず、最新の(もしくは拡張機能に同梱されているバージョンの)`rust-analyzer`をデフォルトで使用するようになっているため、以下のようなエラーメッセージが表示されることがあります。 27 | 28 | ``` 29 | [coc.nvim] Workspace `/home/hikalium/repo/wasabi/Cargo.toml` is using an outdated toolchain version `1.77.0-nightly` but rust-analyzer only supports `1.78.0` and higher. 30 | Consider using the rust-analyzer rustup component for your toolchain or upgrade your toolchain to a supported version. 31 | ``` 32 | 33 | これを回避するためには、本書のリポジトリで使用されているツールチェインに適合したバージョンの`rust-analyzer`をLSPサーバーとして使用するよう、エディタに指示してあげる必要があります。 34 | 35 | まず、以下のコマンドをwasabiリポジトリの内部で実行して、`rust-analyzer`の実行ファイルパスを確認します。 36 | 37 | ``` 38 | $ rustup component add rust-analyzer && rustup which rust-analyzer 39 | info: component 'rust-analyzer' for target 'x86_64-unknown-linux-gnu' is up to date 40 | /home/hikalium/.rustup/toolchains/nightly-2024-01-01-x86_64-unknown-linux-gnu/bin/rust-analyzer 41 | ``` 42 | 43 | その後、このファイルパスをエディタの設定に追記します。 44 | 45 | - Neovimで`coc.nvim`経由で`coc-rust-analyzer`を利用している場合は、エディタを開いて`:CocConfig`もしくは`:CocLocalConfig`を実行して開かれたファイルを 46 | - VSCodeで[`rust-analyzer`拡張機能](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)を利用している場合は、wasabiレポジトリの配下で`.vscode/settings.json`を 47 | 48 | 開き、次のアイテムを追加します: 49 | 50 | ``` 51 | { 52 | "rust-analyzer.server.path": "/home/hikalium/.rustup/toolchains/nightly-2024-01-01-x86_64-unknown-linux-gnu/bin/rust-analyzer" 53 | } 54 | ``` 55 | 56 | 設定を保存したのちエディタを再起動すれば、wasabiに対しても`rust-analyzer`が問題なく動作するようになるはずです。 57 | 58 | See also: 59 | 60 | ## 本書を読む前に、Rust言語に関して理解しておいた方がいい内容はありますか? 61 | 62 | 本書はRust初心者の方でも、それ以外のプログラミング言語の経験がある方であれば問題なく読めることを目指して書かれているため、事前学習は必ずしも必要ではありません。どうしても事前に予習したい場合や、読んでいる途中で参考書が欲しくなってきたら、以下の資料を参考にするとよいでしょう。 63 | 64 | - [The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/) 65 | - こちらはRust言語の公式チュートリアル([英語版](https://doc.rust-lang.org/stable/book/))を日本語に翻訳したものです。Rustの基礎を学ぶ際にちょうどよい、信頼できる情報源となっています。 66 | - [Comprehensive Rust 日本語版](https://google.github.io/comprehensive-rust/ja/) 67 | - こちらの資料は、Rustの利用を推進している会社のひとつであるGoogle社のソフトウェアエンジニアが、社内のRust講座で使用するために書き上げたドキュメントをオープンソース化したものです。こちらも[英語版](https://google.github.io/comprehensive-rust/)が原文となっています。講義形式の内容になっているため、時間を区切ってコツコツ進めたい場合に便利です。また、この資料を利用して講義を運営する人向けのアドバイスも書かれているため、複数人で学習する際にも役立つかもしれません。 68 | 69 | また、本書とあわせて、もしくは本書の次に読むと理解が深まると思われる資料はこちらです。 70 | 71 | - [並行プログラミング入門 ―Rust、C、アセンブリによる実装からのアプローチ](https://www.oreilly.co.jp//books/9784873119595/) 72 | - こちらの書籍は、人類には早すぎた「並行プログラミング」という複雑な問題を、様々な言語による実装を交えつつ解説してくれる良書です。 73 | - [Writing an OS in Rust 日本語版](https://os.phil-opp.com/ja/) 74 | - こちらの一連のブログ記事は、RustでOSを実装する際に必要となる知見が非常に多く掲載されており、筆者も大いにお世話になった情報源です。本書でも、いくつかの箇所でこのブログに言及しています。こちらも[原文](https://os.phil-opp.com/)は英語ですが、有志により翻訳されているため日本語で読むことができます。 75 | - こちらのブログ記事を題材にした輪読会に筆者は以前参加しており、その際の録画アーカイブが[YouTubeのプレイリスト](https://www.youtube.com/playlist?list=PL8U-_gKA4tWtNXVnqYRmn8En5Nh6xzADO)にまとめてありますので、睡眠用BGM等としてお役立てください。 76 | 77 | さらに発展的なOS自作に関わる情報を手に入れたい方は、筆者だけでなくたくさんの自作OS開発者が集うコミュニティ[osdev-jp](https://osdev.jp/)のSlackへの参加を検討してもよいでしょう。参加方法は[こちら](https://osdev.jp/joinus.html)に記載されています。また、定期的に「自作OSもくもく会」や「作業会」という[イベント](https://osdev-jp.connpass.com/)が開催されておりますので、そちらに参加して本を読み進めるというのもありかもしれません。これらのイベント等の動画アーカイブは[YouTubeのプレイリスト](https://www.youtube.com/@osdev-jp/playlists)にありますので、こちらもあわせて参考にしてみてください。 78 | 79 | ## rustfmtでuseの内容を自動でバラしてほしい 80 | 81 | 初版第1刷p.139で、useを行ごとにバラすようにしているよう説明しています。 82 | これを自動でやってくれる方法があると読者より教えていただいたので共有します。 83 | [(Thanks @lapla-cogito!)](https://github.com/lowlayergirls/wasabi-help/issues/7) 84 | 85 | `rustfmt.toml`で 86 | `imports_granularity = "Item"`と設定すれば、自動でバラしてくれるようです。 87 | --------------------------------------------------------------------------------