最終更新: 2026-08-27 統合元: APP_PACKAGE_DESIGN.md / HTTPS_DESIGN.md / network_and_browser_architecture_plan.md
AtmOS は Raspberry Pi 3B+(BCM2837 / Cortex-A53 ×4)向けのベアメタル OS で、 no_std Rust で実装されている。レイヤは下位(ハードウェア直結)から上位(アプリ)へ 積み上がっており、本仕様書も以下の順序で土台から説明する。
| 層 | 主担当モジュール | 役割 |
|---|---|---|
| ブート | boot.S, kmain |
スタック設定・BSS クリア・フレームバッファ確保 |
| メモリ | mmu.rs, allocator.rs |
恒等マップ MMU・キャッシュ・512MB ヒープ |
| 実行基盤 | scheduler.rs, interrupt.rs,
timer.rs |
SMP プリエンプティブスケジューラ・10ms タイマ |
| デバイス | mailbox.rs, draw.rs, dma.rs,
usb.rs, sdio.rs |
GPU FB・DMA 転送・USB(DWC2)・SDIO |
| 入力 | keyboard.rs, ime.rs,
shortcut_manager.rs |
キー入力・日本語 IME・ショートカット |
| ネットワーク | net/(mod.rs/arp/dhcp/dns/icmp/tcp/udp/http),
net_stack.rs, tls.rs,
wifi.rs |
TCP/IP・DHCP・DNS・TLS・WiFi(FMAC) |
| アプリ層 | window_mgr.rs, apps/* |
ウィンドウ管理・ブラウザ・Note・ターミナル等 |
| 言語 | os_lib/aura/* |
Aura 解釈系(AURA.md) |
kmain(main.rs)の初期化順序は依存関係で決まっている。
フレームバッファ確保を MMU 有効化より前に行うのは、GPU と D-Cache
のコヒーレンシ問題を避けるため。

キーボードショートカットの全一覧は本ファイル §15「キーボードショートカット」を参照 (ガイドバー
fn_bar.rsの実装もこの一覧を単一の真実とする)。本書 §6 は設計意図を述べる。
TCP/IP モデルをベースに、モジュール性・並列性・疎結合を重視した構成。各層は独立したモジュールとして実装し、共通のパケットバッファ管理機構でデータをやり取りする。
第1層: Link Layer(ネットワークインターフェース層)
- eth_send(), eth_register_recv_callback() を
API として提供 - NIC
からの割り込みを受け取り、生のフレームを送受信するハードウェア依存モジュール
第2層: Internet Layer - IPv4: IP
ヘッダパース、ルーティング、フラグメンテーション - ARP:
IP→MAC 解決、ARP キャッシュテーブル管理 - ICMP: Ping
等の診断・エラー通知 - ip_send(),
ip_register_protocol_handler() を API として提供
第3層: Transport Layer - UDP: コネクションレス軽量転送(DNS 等で利用) - TCP: コネクション指向・スライディングウィンドウ・再送制御。ステートマシンで非同期動作 - BSD Socket ライク API + 非同期・イベント駆動インターフェースを提供
第4層: Application Layer - DNS
Resolver: UDP
モジュールを使用してドメイン名を解決。ping
などのユーティリティや各種ネットワークAPIで、指定されたIPアドレスのパースに失敗した場合、本リゾルバを用いたDNS解決(dns_query_a_via_udp)を自動で試みるフォールバック処理が実装されています。これにより、ホスト名指定による透過的な通信が可能となっています。
- HTTP Client: TCP
モジュール上。リクエスト生成・レスポンスヘッダ解析・Chunked
転送対応。ブラウザ以外からも再利用可能
net_stack.rs を新設し LinkLayerApi /
InternetLayerApi / TransportLayerApi /
ApplicationLayerApi を定義済みTcpIpError { layer, message }
でレイヤ識別つきエラーを実現TcpIpStack 実装で既存
net/(tcp/udp/dns
等)/ tls.rs をアダプト。入口 web_get()
を提供web_engine の実通信経路を
net_stack::TcpIpStack 経由に切り替え済みアプリ(ブラウザ等)⇄ カーネル内部の境界は
ApplicationLayerApi /
TcpIpStack::web_get・web_post・
web_get_binary
に一本化する。この入口で全入力を検証し、通過後はカーネル内部(DNS/TCP/TLS/HTTP
パーサ)が 「検証済みの host/path
しか来ない」前提で動けるようにする(OS
内部とアプリの疎結合)。
net_stack::validate_web_request(host, path):host は
A-Za-z0-9.- の 1..=253 バイト、path は /
始まりの 1..=4096 バイトで制御文字・CR/LF を排除(HTTP
ヘッダインジェクション防止)。POST ボディは 8MB 上限。TcpIpError(Application
層)で返す。アプリの不正要求で OS が落ちない。&str
のバイト境界スライスを避け(parse_http_response
はバイト単位でチャンク復号)、
添字/スライスは長さ確認後に行う。unwrap/expect
は clippy で deny。
パニック予防リント(クレート全体で施錠済み
2026-06-16): 過去のカーネルパニックは 2 度とも
「&str をバイト境界でスライスして UTF-8 文字の途中で
panic」が原因。これを精密に捉える clippy::string_slice を
main.rs で crate 全体に
#![deny] 化した(段階導入を完了し全面施錠)。 全
100 箇所の &str スライスを撤去し、位置は
find()/strip_prefix()(ASCII ニードル=必ず
char 境界) 由来か str::get(range)(範囲外・境界違反で
None)で安全化した。添字が必要な低レベル処理は
&[u8] に対して行う(本リントは &str
のみ対象)。unwrap/expect も既に clippy
deny。cloud 応答ログの
&resp.body[..96](×3・任意 HTTP 本文の
固定バイト切り)を文字境界安全な head_str()
に、web_engine の &html[..120](HTML
先頭ログ)を 境界 walk に、css::resolve_css_var の末尾
var( での after[1..] 範囲外を
str::get に修正。indexing_slicing(約2475件・大半が固定長配列の誤検知)は不採用のまま。
パニック回復時のロックリーク対策(実装済み
2026-06-15): panic=abort で unwind が無いため、
ロック保持中にプロセスが死ぬと MutexGuard の Drop
が走らずロックが永久保持→以後デッドロック。 対策として
kernel/reclock.rs に保持コア ID を記録する
RecoverableMutex を新設し、NET_LOCK/
USB_LOCK
を置換、ヒープアロケータ(Locked)にも保持追跡を追加。#[panic_handler]
は復旧処理の 最初に当該コアが保持中のロックだけを
force_release_if_core(cid) で強制解放する(他コアの正当な
保持には触れない)。特にヒープロックは直後の
println!(=確保) が取りに行くため最優先で解放する。
reclock::selftest()(leak→誤コア解放されず→正コア解放で再取得可)で
RECLOCK_SELFTEST: PASS(CI ガード)。Resource Fetcher HTTP Client API 経由で HTML/CSS/画像を非同期取得・キャッシュ
HTML Parser バイト列→DOM ツリー構築
CSS Parser スタイルシート→CSSOM 構築
Layout Engine DOM + CSSOM →レイアウトツリー・ボックスモデル計算
Paint/Render レイアウトツリー→AtmOS グラフィック API 呼び出し→描画
HTML パーサ改善: -
属性パース強化(引用符付き値、空白を含む属性値、属性値省略) - Void
要素判定拡張(input, meta, link,
source など) - コメント・DOCTYPE 等
<!...> の読み飛ばし追加
CSS 対応強化: - css::parse_css()
実装。selector { key: value; } を解析 - セレクタ対応:
tag, #id,
.class、カンマ区切り、descendant(空白)、child(>)
- 複合セレクタ: div.note > p.warn のようなチェーン形式 -
specificity(id > class > tag、同点は後勝ち) - 疑似クラス
:first-child / :last-child を最小対応 -
border-style / border-color(none
/ dashed / solid)の最小対応 -
text-align: center / right の最小対応 -
font-weight: bold(b/strong
タグ・CSS で有効化、1px 重ね描きでシミュレーション) - CSS
スタイル継承修正: color / font-size /
font-weight を flatten_layout
経由で親→子へ伝播
レイアウト拡張: - block コンテナ内の inline
フロー(行内配置・折り返し) - br を改行として処理 - box
model: margin / padding /
border-width / 各辺プロパティをレイアウト計算に反映 -
display: inline-block 最小対応 - 幅解決で % /
auto / min-width / max-width
を反映
CONTROL_BAR_H = 40px。コンテンツ描画開始 Y は
WebBrowser::top_offset()
が唯一の境界定義で、
描画・クリック判定・レイアウト・全起動経路(Aura app() /
files アプリ)が共通参照する。 マジックナンバー(旧 40/65
の混在)は禁止。MAX_RENDER_ELEMENTS = 20000 個、パース対象 HTML は
MAX_HTML_BYTES = 2MB で打ち切る(ヒープ枯渇の予防)。各タブが独立した WebEngine
を持つ完全分離方式(URL・描画済み DOM・スクロール・
フォーム入力・履歴がタブごとに保持され、切替でネットワーク再取得しない)。
WebBrowser.engine
はアクティブタブのライブエンジン。tabs: Vec<TabSlot>
の TabSlot { title, engine: Option<WebEngine> }
で、アクティブタブのスロットは
engine: None(ライブへチェックアウト済み)、非アクティブタブは
Some(engine) を保持。activate(idx): core::mem::swap
でライブと切替先スロットのエンジンを入れ替える
(クローンも再取得もなし。WebEngine は move
のみ)。add_tab: 新規 WebEngine
を生成してライブに、旧ライブを元スロットへ退避。上限 16 タブ。load_page 再取得)から移行。
メモリは増えるがタブ操作が即時化し入力・スクロール・結果が保持される。self.engine がアクティブエンジンを指すため変更不要。layout_block /
layout_inline は、包含ブロックとして渡される
Dimensions.content.height を「現在の Y
フローカーソル」と解釈し、自身を content.y + content.height
に配置する。block 子のレイアウト時は親が
cb.content.height = y_cursor を設定してから
child.layout(cb) を呼ぶ。intrinsic_inline_size()
で寸法を計測し、行ボックス内のスロット位置 (x, y, w, h) を確定する。
その後の child.layout(cb) には height = 0 の
cb を渡し(規約 1 により子が自分の高さぶん
下へずれるのを防ぐ)、呼び出し後に親が確定したスロット寸法を最終値として再設定する
(layout_inline 内の再計算は % 高さを包含高さ
0 基準で解決して潰すため)。 ※ この規則に違反すると「textarea
が自分の高さぶん下(画面外)に飛ぶ」バグが再発する (TECHNOTE §7
参照)。web_engine::flatten_layout と
vector_font::get_string_wrapped_size
が完全に同一の規則('\n'
強制改行・行頭/行末禁則・
改行時に先頭文字を即消費)を持つ。どちらかを変更したら必ず両方を同期する(<hr>
重なりバグの原因)。
エディタ(textarea)表示の折返しは別規則で、WebEngine::wrap_editor_lines(O(n)
実装)に一元化済み。parse_and_layout
は layout::set_viewport_hint(w, h) を設定してから
レイアウトを実行する。置換要素(textarea 等)の
width/height: 100% はこのヒントを基準に解決される。display: table / table-row-group / table-row / table-cell
と <table><tr><td><th> に対応
(layout.rs::layout_table)。 - UA デフォルト display を
css.rs に追加(table→table、tr→table-row、td/th→table-cell、
thead/tbody/tfoot→table-row-group、th は bold + center) -
行グループ(thead/tbody/tfoot)は build_layout_tree で透過し、行を table
の直接の子へ引き上げ - 列幅は各列セルの intrinsic
幅の最大値を基準に、総和が利用幅超過なら比例縮小・
下回りなら均等加算で幅いっぱいに展開。各行を縦に積み、行内セルを列幅で横並び、
行高さ = セル最大高さに揃える -
セルごとの背景色・文字色・text-align・border
は通常のブロック要素と同じく適用 - 注意: layout_block と
inline フローの box_type マッチはテーブル variant も block 扱いで
網羅すること(未網羅だと早期 return でセルが (0,0) に積み上がる)
layout_table を「セル index =
列番号」前提からグリッドモデルへ書き換え、占有グリッドで colspan
/ rowspan を解決。<caption>
を本体上部に配置、border-collapse: collapse 時は 隣接セルを
1px 重ねて二重線を解消。
os_lib/js/)ブラウザの <script> / onclick
を実行する自前の JavaScript エンジン。従来は Aura (Lisp 系)が
<script> を実行していたが、本物の JS へ切替(Aura は
.aura 用に存続)。
lexer.rs(全演算子・コメント・テンプレート)/
parser.rs(再帰下降 + 優先順位 クライミング)/
ast.rs /
value.rs(Rc<RefCell> 参照カウント値)/
bigint.rs(BigInt)/ regex.rs(正規表現)/
intl.rs(Intl)/
dom_bridge.rs(DOM 連携)/ selftest.rs
(JS_SELFTEST)。ツリーウォーク評価器は
interp.rs +
interp/(calls/eval_expr/exec/
operators/properties/dom_props/iter_gen/promise_loop)、標準ライブラリは
builtins.rs +
builtins/(object_array/collections/date/promise/typed_array/
dom/dom_document/events/observers/intl/web_forms/regexp/encoding/
timers_gen/window_api
他)にファイル分割済みdelete・instanceof・in・ラベル付き
break/continue 含む)・eval/ Function
コンストラクタ(常にグローバルスコープで実行する簡略実装。direct eval の
レキシカルスコープ捕捉は対象外)・オブジェクト/配列
(算出プロパティ名・getter/setter・スプレッド/rest)・メンバ/添字/呼出/new・new.target・
三項・論理・try-catch(分割代入パターン対応)・for-of/for-in(反復ごとの束縛対応)・
アロー関数・テンプレートリテラル(タグ付き・String.raw
含む)・分割代入・ class(private field/method・static
field/block・private brand check #x in obj・
算出メソッド名・Symbol.iterator
実装によるカスタムイテラブル)・Map/Set・Proxy
(get/set/has/deleteProperty トラップ、他 API からの透過性を点検済み)・
Map.groupBy/Object.groupBy・Promise(マイクロタスクキュー、all/race/any/
allSettled/try/withResolvers)・async/await・generator(throw/return/next
標準 メソッド一式)・BigInt・TypedArray 一式 +
DataView/ArrayBuffer/Blob・RegExp
(g/i/m/s/y/d
フラグ、名前付きキャプチャグループ、\uXXXX/\xXX
エスケープ、 RegExp.escape。u/v
フラグは対象外)log2/log10/cbrt/hypot
含む)/ JSON(os_lib/json.rs
再利用。replacer/reviver/space/toJSON
フック対応)/
Object(freeze/seal/preventExtensionsとその判定系、defineProperty/
getOwnPropertyDescriptor、fromEntries、プロトタイプ操作)/
Reflect / Array(map/filter/ reduce/sort/flat/flatMap/toSorted 等の
ES2023 非破壊系、Iterator Helpers)/ String
(replaceAll/normalize/at/codePointAt
等)/ Number / Date(NTP 同期済み壁時計に接続、 ISO 8601 パース含む)/
Error
階層(TypeError/RangeError/SyntaxError/AggregateError/
SuppressedError、cause
オプション、Error.isError)/
crypto(randomUUID/ getRandomValues)/
structuredClone(循環参照・Date/RegExp/Map/Set/TypedArray/
ArrayBuffer/DataView/Blob の実体保持に対応)/
setTimeout(マクロタスク)/
WeakMap/WeakSet/WeakRef/FinalizationRegistry(GC 非搭載のため一部 no-op
近似)document.getElementById
/ querySelector。matches/closest/
querySelector(All) は dom_bridge.rs
の共通セレクタマッチャーを使い、コンパウンドセレクタ
(div.active#foo)・属性セレクタ([attr]/[attr=val]/^=/$=/*=/~=)・結合子
(空白/>/+/~)・疑似クラス
:not()/:is()/:where()/:first-child/:last-child/
:only-child/:nth-child()/:nth-last-child()/:first-of-type/:last-of-type/:only-of-type/
:nth-of-type()/:nth-last-of-type()
に対応(:hover/:has()/:scope
等は非対応のまま静かに無視)。textContent /
style / classList、
addEventListener /
removeEventListener(capture /
once オプション対応)/ dispatchEvent。
イベントは capture → target → bubble の 3
フェーズで親要素のリスナまで発火し(イベント委譲)、 Event
オブジェクトは type / target /
currentTarget / eventPhase /
bubbles / preventDefault() /
defaultPrevented / stopPropagation() /
stopImmediatePropagation() を提供。
os_lib/web_engine/render.rs
の on_mouse / キー処理から発火):
click / mousedown /
mouseup / dblclick / mousemove /
mouseover / mouseout / mouseenter
/ mouseleave / wheel /
contextmenu(右クリック)。MouseEvent には
button / buttons / detail /
offsetX / offsetY / movementX /
movementY と 修飾キー(shiftKey /
ctrlKey / altKey /
metaKey)を付与。keydown / keyup /
keypress(文字生成キーのみ)。KeyboardEvent
には標準の key / code(KeyA /
Digit1 / Enter / ArrowLeft 等)/
keyCode / which / charCode /
location / repeat
と修飾キーを付与。特殊キーは標準 code と legacy
keyCode へマッピング。focus / blur
と、そのバブリング版 focusin / focusout。input / change /
submit。kernel/keyboard.rs
がグローバル修飾キー状態を AtomicU8 (bit0=Shift /
bit1=Ctrl / bit2=Alt / bit3=Meta)で公開し、main.rs
の入力パイプラインから同期。 JS 層の各イベントはこれを読んで
shiftKey 等を埋める。WindowMgrApp::on_mouse トレイトは btn_left /
btn_right / wheel
を受け取り(main.rs のマウス/タブレット両入力経路と
window_mgr.rs が伝搬)、 エンジンは右ボタンの押下エッジで
contextmenu を発火する。preventDefault()
は文字入力・送信・スクロール等の既定動作を抑制する。 クリック互換のため
JsRuntime::dispatch_click も従来どおり利用可能。interp はステップ予算(既定
5,000,000)とJS再帰深度上限(既定 400)を持ち、超過時は
aborted を立てて catch されずに最上位まで巻き戻す。structuredClone・JSON.parse・JSON.stringify
などの Rust 側再帰処理には、深さ上限 30
のガードを適用している。これは AtmOS の初期コアスタックが
64KB(boot.S)と極めて小さく、二分探索実測により深さ
80 段以上で Stack Overflow
クラッシュ(無応答)を引き起こすためである。JSON 規格 RFC 8259 §9
(“Parsers”) ではパーサが独自にネスト深さの上限(maximum depth of
nesting)を定めることが明確に規定・推奨されており、業界標準の防御壁(Cloudflare
WAF 等のネスト制限
20〜30)と同等の安全性・実用性を満たす仕様となっている。Rc)。循環参照はリークするが、ページ遷移ごとに
JsRuntime を 破棄して回収するjs::selftest()
が多数のケースを評価し JS_SELFTEST: PASS n/n を
シリアル出力(test_browser.sh / CI でガード)embedded-tls クレートで実装。alloc feature
有効化で RSA 証明書に対応| 方式 | 長所 | 課題 |
|---|---|---|
| rustls + ring 系 | Rust 中心で保守しやすい | no_std + ARM64 ベアメタル適用の調査コスト高 |
| BearSSL C 連携 | 軽量で組込み実績が多い | FFI 境界とメモリ安全の管理が必要 |
| TLS 終端プロキシ | 実装が最短 | OS 単体の完全性が下がる |
→ 第一候補は embedded-tls(rustls 系)。2
週間以内に成立見込みが薄ければ BearSSL 連携へ切り替え。
src/tls.rs: TLS ラッパー(embedded-tls
ベース)src/net_stack.rs: TcpIpStack で TLS
経路を抽象化https get [host] [path](シェルから実行可能)ARM64 の例外レベルを適切に分離し、カーネル空間および主要サービスを EL1(特権モード)、ユーザープロセスを EL0(非特権モード)で動作させる。
以下はすでに実装済み:
src/vector.S: EL1/EL0 分離の例外ベクタsrc/scheduler.rs: spawn_user_on_core で
EL0 プロセスを起動src/mmu.rs: ページ保護属性で EL0
からのカーネル領域アクセスを禁止src/syscall.rs: SVC ハンドラで SYS_PRINT /
SYS_YIELD / SYS_EXIT を実装main.rs にはテスト用の user_test_normal /
user_test_abort
が実装済みだが現在は無効化(コメントアウト)。
spawn_user_on_core
による起動有効化QEMU 起動後、UART 出力で以下を確認: 1.
USER_TRAMPOLINE: Entering EL0 が出力される 2.
SYS_PRINT で文字列が表示される 3. SYS_EXIT
でプロセスが正常終了する 4. MMIO への不正アクセスで
=== DATA ABORT from EL0 === が発生し、OS
全体はハングせず継続する
main.rs
の巨大なメインループにショートカット判定とマウス移動計算がハードコードされており、デグレが頻発していた。これを独立モジュールとして分離した。
ShortcutLayer 列挙型: OS /
App / User の 3 レイヤShortcut 構造体:
キーコード・修飾キー状態・アクション・weight(同時押しキー数)MouseTracker: 現在 x, y
座標と screen_width, screen_height を保持move_relative(dx, dy):
相対移動。0〜width-1 にクランプmove_absolute_tablet(abs_x, abs_y, max_x, max_y):
タブレットの絶対座標を画面解像度にマッピングmain.rs のメインループ内のハードコードされた境界計算を
mouse_tracker.move_relative(dx, dy)
に置き換え済み。キーボードイベントは
shortcut_manager.evaluate()
に渡して返ってきたアクションのみ実行。
アプリは長らく EL1 カーネル空間で Box<dyn App>
として動作し、カーネルと同一ヒープを共有していた。
このためアプリ操作(例: ウィンドウ最大化の連打)で OS
全体がフリーズする事故が発生した。
原因の多くは「効果音ごとのスレッド生成・破棄チャーン」や「リサイズ毎の巨大バッファ再確保」で、
アプリ層の不調がカーネルのヒープ canary
を壊していた。これを段階的に是正する。
Window::resize(w, h)
を新設。バッファは容量が足りていれば再利用し、不足時のみ再確保する。stride = width で先頭
width × height
要素のみ使うため、より大きいバッファの再利用は安全。resize() 経由に統一。resize()
は拡張確保の前にヒープ残量を確認し、不足ならリサイズを拒否して旧状態を保つ。spawn
と同様の事前チェック方針)。kernel/watchdog.rs。app.draw() を
watchdog::enter/exit で挟み実行時間を計測。check_from_irq()
を呼び、描画が予算(既定 800ms)を大きく超えて張り付いていれば
ハングとしてログ通報する。実装済みの基盤(検証済み):
spawn_user_on_core)、SVC
システムコール(SYS_YIELD/EXIT/PRINT/...)。vector.S の EL0 同期例外ハンドラが SVC・Data
Abort・Instruction Abort・その他の全例外を振り分け、 フォルト時は
rust_data_abort_handler → scheduler::exit()
で当該プロセスのみ終了する。user_test_abort が EL0 から MMIO
へ不正アクセス → DATA ABORT from EL0 → プロセス kill。
同時に user_test_normal は継続し、OS 本体(WM
等)も正常稼働することを確認済み。→ つまり「EL0 で動くコードがフォルトしても OS は落ちない」という核心の安全性は確立している。
EL0 GUI ウィンドウ ABI(実装済み・QEMU 検証済み):
kernel/user_win.rs + syscall.rs
に以下を実装。EL0 プロセスは WM・フレームバッファに
直接触れず、システムコール経由でウィンドウを操作する。
| syscall | 番号 | 機能 |
|---|---|---|
SYS_WIN_CREATE |
5 | x0=リクエスト構造体 [title_ptr, title_len, w, h] →
ハンドル返却。カーネル側に UserApp プロキシを生成し WM に登録 |
SYS_WIN_BLIT |
6 | x0=ハンドル, x1=ピクセル列 (ARGB8888, w×h)。カーネルが検証してコピー |
SYS_WIN_POLL |
7 | x0=ハンドル, x1=書込先。入力イベント (Key/Mouse/Closed) を1件取得 |
SYS_WIN_CLOSE |
8 | ウィンドウ破棄・レジストリ解放 |
UserApp(App
トレイト実装のプロキシ)が共有ステート(ピクセル・イベントキュー)を
介して EL0 と通信。Drop
実装によりどの経路でウィンドウが閉じても EL0 へ CLOSED
が通知される。user_pixel_demo(.user_text)。全描画・入力処理を
EL0 で行うピクセルデモ。 ターミナルから
os:launch_gui("eldemo") で起動。QEMU でウィンドウ生成・連続
blit・ 破損ゼロを確認済み。残作業(段階移行):
移行が完了すると、アプリのバッファオーバーフローや無限ループはカーネルへ波及せず、 MMU 保護で Data Abort になり当該ウィンドウのみが落ちる構造になる。
| 物理アドレス範囲 | 容量 | 用途・詳細 |
|---|---|---|
0x0000_0000 〜 0x0040_0000 |
4.0 MB | ブートローダ予約、例外ベクタテーブル、カーネル本体(.text/.data/.bss)、CPUスタック(4コア×64KB) |
0x0040_0000 〜 0x2040_0000 |
512.0 MB | カーネル動的ヒープ領域(TLSF): Webエンジン(DOM/CSS/JS)、プロセス、画像、通信等の専用空間 |
0x2040_0000 〜 0x3800_0000 |
380.0 MB | SylFS 専用 RAMDisk 物理ストレージ領域: ヒープ消費ゼロで直接マッピング(一時キャッシュ/非多重化) |
0x3800_0000 〜 0x4000_0000 |
128.0 MB | GPU / VRAM / MMIO レジスタ領域: フレームバッファ(gpu_mem=128)および BCM2837 MMIO レジスタ |
kernel/allocator.rs。512MB のカーネルヒープを管理する。
TLSF (Two-Level Segregated Fit) 方式により最悪計算量 O(1)
の確保・解放と有界な断片化制御を実現している。
HEAP_START ──────────────── frontier ──────────────── HEAP_END
[確保済み/解放済みブロック群] [未使用 (pristine) 領域]
↑ フリーリストで再利用管理 ↑ ポインタ前進だけで確保
gui_shell(クリティカル)の alloc 失敗 →
カーネルパニックに直結していた(TECHNOTE §6)| 層 | 機構 |
|---|---|
| canary | 全ブロックヘッダに FREE_MAGIC /
ALLOC_MAGIC を刻印。alloc/dealloc/走査時に検証 |
| 走査ガード | フリーリスト walk は上限回数つき(循環参照対策)。不正 next は切り詰め |
| repair() | 破損検出時にヒープを物理走査してフリーリストを再構築(孤立ブロック救済) |
| integrity_check() | 定期診断(USB ポーリングスレッドから実行)。最初の破損の現場を保全ログ |
| OOM dump | 確保失敗時に要求サイズ・再利用プール・pristine 残量をダンプ |
alloc API は確保失敗 =
即パニック(handle_alloc_error)のため、 null
を返してからの復旧は不可能。「失敗させない」ことが唯一の防御であるget_heap_stats()
で残量を確認し、不足時は操作を拒否して継続する本仕様は、外部の中継プロキシを排除し、ラズパイ3B+のベアメタル環境(no_std)のみでインターネットから直接mp4形式のYouTube動画を取得・デコードし、映像と同期した音声をHDMI(I2S)およびイヤホンジャック(PWM)の両系統から完全同期で出力するためのものである。
src/os_lib/mp4.rs):
moov ボックス内の
trak
トラック情報を解析し、映像/音声の各サンプルのファイルオフセット、データサイズ、タイムスタンプ(ミリ秒単位)、およびキーフレームフラグを正確に特定。src/os_lib/h264.rs +
src/os_lib/h264_decode.rs):
no_std 下で動作する本物の Baseline Profile
デコーダ(旧実装は「簡易レンダリング(模倣)」のモックで撤去・再実装)。ffmpeg/x264
出力とビット完全一致。src/os_lib/h264_golden.rs、I/P・deblock
有無 計11本)をデコードしリファレンス YUV と ビット一致
で確認(h264_decode::golden_test()
を起動時実行、H264_GOLDEN/H264_SELFTEST/H264_TABLES)。avcC 抽出)、逆量子化 + 4x4 整数
IDCT。mp4.rs が avcC から SPS/PPS と
NAL
長さサイズを取り出し、h264_decode::VideoDecoder(参照フレーム保持)が
AVCC サンプルを復号、YUV→RGB(BT.601)を web_engine
の再生スレッドへ供給。ウィンドウへ Nearest Neighbor
スケーリングで描画。src/os_lib/mp3.rs):
no_std デコーダ。src/kernel/audio.rs):
clean_dcache_range
を実行してキャッシュをクリーンし、DMA 3 / 4 を同時に活性化(ACTIVE |
PRIORITY=8)して同期転送。src/os_lib/web_engine.rs):
scheduler::spawn で
video_playback_thread を優先度 High で開始。http_get_binary
を介して動画データを一括ダウンロード(ポート番号パース付き)。Audio::play_pcm_stream
に流し、ハードウェアDMAに非同期で再生させる。get_system_time_ms()
からの経過時間と映像サンプルの timestamp_ms
を比較し、タイミングが来たら H.264 デコードを行い、共有バッファ
CURRENT_VIDEO_FRAME に最新フレーム(RGB)を書き込む。WebEngine::draw メソッド内で
CURRENT_VIDEO_FRAME からフレームを取り出し、ウインドウの
draw_x_base, draw_y
オフセットとクリッピング境界を考慮して、動画エリア(400..800px可変幅)へ
Nearest Neighbor 描画。self.video_playing == true)は、ブラウザアプリ側の
needs_timer_redraw が true
を返し続け、再描画フラグ self.dirty = true
を維持して毎フレーム更新ループを強制回転させる。stop_request
を送り、オーディオを消音する(以前存在した youtube.com
等の入力に対する
http://youtube.atmos-project.org/youtube/stream
への強制自動リダイレクト処理は、本物 YouTube
アクセス解禁に伴い廃止されました)。不要な列の排除による視認性向上と、詳細情報の確認スペース拡大のための仕様。
src/kernel/window.rs)Info
列の表示領域をペイン幅の 55%(以前の CPU
列の位置)から開始させるように変更。SortColumn::NameSortColumn::InfoSortColumn::Cpu / SortColumn::Ram
列に対する定義とソート比較条件自体は、下位互換性およびデバッグ用としてコード上に保持する。ターミナル(CUIシェル)はAura言語インタプリタを評価するスレッドと、非同期にキュー(SafeQueue)を介して通信を行っていますが、特定のローカルコマンドはAuraの評価エンジンを通さず、UIスレッド(shell.rs
内の
execute_shell_command)で即時に処理して完了(インターセプト)させます。これにより、インタプリタのバグや遅延から遮断された頑健なシェル操作を保証します。
clear
history / h
history: Vec<String>
から、インデックス(1始まり)を付与した文字列リスト(例:1 ls)をフォーマットして
print_line() で即時に表示します。self.history
の不変イテレートと print_line による self
の可変参照)を防ぐため、履歴データをクローンしてからイテレート処理を行います。[Terminal] Executing local history command
のカーネルログ(info!)を出力します。parse_launch_options)アプリケーション起動時に渡された引数を解析し、初期ウィンドウの表示状態(maximized、normal、minimized、fullscreen)およびサイズを動的に決定します。
"800x600" のようなサイズ直接指定(数字
+ "x" + 数字)が存在する場合、状態を強制的に
"normal"
に設定したうえで、指定サイズでウィンドウを起動します。"normal",
"maximized", "minimized",
"fullscreen")を解析します(未指定時のデフォルト状態は
"maximized" となります)。cleaned_args)から安全に除去されます。"normal" 状態時)通常表示状態で起動される場合のウィンドウサイズは、以下の優先順位に従って決定されます。
1. 起動引数でのサイズ直接指定(例: "800x600") 2.
アプリケーションマニフェスト(manifest.json)の
width および height 定義値 3.
システムデフォルトサイズ(一律 500x600)
システム起動時および運用時のコンソールログ(シリアル出力)の視認性を高め、不要なログスパムを防止するための出力規則です。
log! マクロ(info!, warn!,
error!,
debug!)が出力するログのレベルプレフィックスは、大文字5文字幅に統一・アライメントされます。
- [ERROR] : システムエラーや例外(Data Abortなど) -
[WARN ] : 警告(フォールバック検知など) -
[INFO ] : 各モジュールのマイルストーンや完了ステータス -
[DEBUG] : 開発者向けの詳細情報
ログ出力メッセージの先頭には、括弧で囲んだ大文字のモジュール名(大文字3〜5文字)を明示します。
- [SYS] : システム全体、初期化共通、例外ハンドラ -
[GPU] : グラフィック、FrameBuffer、V3D - [MMU]
: メモリ管理、ページテーブル - [MEM] : ヒープアロケータ -
[FS] : ファイルシステム (SylFS)、ブロックデバイス -
[USB] : USB ホストコントローラ (DWC2)、HIDスタック -
[AUD] : オーディオエンジン - [SCHED] :
スケジューラ、プロセス管理
例:
[INFO ] [USB] Device Speed: High Speed (PrtSpd=0)
IS_SILENT)の活用テスト実行時(js, fs, usb
などのセルフテスト)や、ファイルシステムの初回マウント時(未フォーマットの空セクタ読み込み時)には、グローバルなサイレントフラグ(kernel::uart::set_silent(true))を一時的に有効化します。これにより、期待される擬似的なエラーログや不要な警告ログがコンソールに出力され、ログが汚れるのを防止します。
kmain (起動時)
では、以下の7つの主要ステップに絞り、右端に [OK]
を揃えたクリーンなサマリーを表示します。これ以外の不要な詳細ログは
info! 以下に落として起動時には非表示にします。 1.
Graphics System (FrameBuffer) ................. [OK] 2.
Memory System (MMU & Heap) .................... [OK] 3.
Core Software Self-Tests (各テストのPASSマーカー) [OK] 4.
File System (SylFS) ........................... [OK] 5.
Audio Systems ................................. [OK] 6.
USB Host Controller & HID Stack ............... [OK] 7.
System Scheduler & Interrupts ................. [OK]
expect)との互換性QEMU自動テスト(expect test_browser.sh)が監視する各セルフテストの合格判定文字列(JS_SELFTEST: PASS
など)は、サマリー表示の第3ステップの1行の中にすべてテキストとして埋め込む形で出力されます。これにより、テストスクリプトの検知ロジックを壊すことなく、出力行数の削減を実現しています。
AtmOS のアプリは 静的リンク(モノリシックビルド)+ 仮想マニフェスト の組み合わせ。
src/apps/{name}/ の Rust
コードがカーネルと一緒にコンパイルされ kernel8.img
に含まれるfs/mod.rs
がプリインストールアプリのマニフェスト(manifest.json,
main.aura)を SylFS の /apps/{name}/
に動的生成main.aura を評価→os.launch_gui("name") →
builtins.rs でアプリ判定→静的リンク済み Rust
構造体をインスタンス化してウィンドウにバインド将来改善案: include_str!
でアセットをアプリモジュール自身に持たせ、fs/mod.rs
からハードコードを排除(作戦A)。
| キー | 機能 |
|---|---|
ESC |
モーダル・IME 変換を閉じる |
F1 |
ターミナルへフォーカス(再押下でスライドトグル) |
| キー | 機能 |
|---|---|
Alt+F1〜F8 |
ワークスペース 1〜8 へ移動 |
Alt+F9 |
最小化 |
Alt+F10 |
通常状態へ復元 |
Alt+F11 |
最大化 |
Alt+F12 |
全画面(新規ワークスペース) |
| キー | アクション |
|---|---|
Alt+T / Alt+W |
タブ追加 / 閉じる |
Alt+↑ / Alt+↓ |
タブ切り替え |
Alt+O / Alt+S |
ファイルを開く / 保存 |
変換(0x79) / 無変換(0x7B) |
IME ON / OFF |
Ctrl+A/E(行頭/末)、Ctrl+K(行末削除)、Ctrl+C(クリア)、↑↓(ヒストリ)、Shift+Enter(改行)
Ctrl+A/E(行頭/末)、Ctrl+F/B/N/P(移動)、Ctrl+O(Open
Line)、Ctrl+S(検索)
Space(変換/次候補)、Enter(確定)、1〜9(番号選択)、Esc(取消)
kernel8.img 等)— AtmOS
からの書き込みを完全ブロック+524288
セクタオフセットを付加し、ブート領域を保護0x3F20_2000(BCM2837 Peripheral)SDCMD/SDARG/SDRSP0-3/SDDATASDCDIV
制御)include_bytes!
で埋め込んだデフォルトアセットcolorset.json/config.json
のパース失敗時は自動的に .bak 退避 → デフォルト再生成# sdcard.img をオンボード SD スロットとしてアタッチ
-drive file=sdcard.img,if=sd,format=rawarm/v1/tests/
ディレクトリ内に専用テストクレート atmos_unit_tests
を配置。src/ の非汚染:
カーネルソース側に #[cfg(test)]
やテスト用コードを一切埋め込まない。make test):
arm/v1/Makefile 内の make test
ターゲットにより、ホスト環境 (std)
でミリ秒単位の超高速実行・一括検証を実現。arm/v1/tests/src/lib.rs から
#[path = "../../src/..."] 属性でモジュールを直接参照。std 環境で参照不可能なハードウェア依存(MMU, UART,
割り込み等)およびカーネル内グローバル状態は、tests/src/lib.rs
側で必要最小限のモック/スタブ構造体(Color,
KeyRepeatParams, DummyFs
等)として定義・提供。arm/v1/
├── src/ ← カーネル本体ソース (no_std / AArch64)
└── tests/ ← 独立ユニットテストクレート (std / Host)
├── Cargo.toml
└── src/
├── lib.rs ← モジュールマッピング & モック定義
├── test_dom.rs
├── test_css.rs
├── test_js.rs
├── test_aura.rs
├── test_keyboard.rs
└── ... ← 各機能モジュールの独立テスト群
[ カーネル・スタック 4MB ][ ヒープ 512MB ][ 専用 RAMDisk 380MB ][ GPU / MMIO 128MB ]
0x0000_0000 0x0040_0000 0x2040_0000 0x3800_0000 0x4000_0000
RAMDisk
をヒープから動的確保するのをやめ、ヒープ直後の物理空き
RAM(0x2040_0000 〜 0x3800_0000)を
直接使うようにした(block::RAMDisk::from_raw_memory)。
ヒープ(512MB)を 1 バイトも消費せず丸ごとアプリケーションへ残し、さらに
RAMDisk
は揮発性メモリのため多重化(ミラーリング)を行わず、380.0MB(100%)全域を実効容量として使用する。
この配置は 3 つの値の関係だけで決まる。
| 値 | 定義場所 | 設定値 |
|---|---|---|
| ヒープの大きさ | allocator::KERNEL_HEAP_SIZE |
512MB (0x2000_0000) |
| RAMDisk の開始 | ヒープ末尾(__cpu_stacks_end + KERNEL_HEAP_SIZE) |
0x2040_0000 |
| GPU 境界 | mmu::DEVICE_REGION_START |
0x3800_0000 |
どれかがずれると、記憶装置への書き込みがヒープや フレームバッファを壊す。 症状は「どこかが時々壊れる」で、 原因の特定が極めて難しい。
main.rs と fs/mod.rs が別々に
512 * 1024 * 1024 と
書いていたのを統一し、allocator::KERNEL_HEAP_SIZE
を唯一の定義として参照する。
tests/src/test_memory_layout.rs: - RAMDisk
がヒープに重ならない - RAMDisk が GPU 領域を踏まない - 0x0040_0000
起点時の 380.0MB(100%)実効容量と一致する -
ヒープが大きすぎても引き算が桁あふれしない -
非多重化(100%)により全 380MB をフル活用できること - 1024MB
物理メモリ全体(0x0000_0000 〜 0x4000_0000)が 1
バイトの隙間もなく連続していること
[FS] Dedicated RAMDisk allocated from 0x20400000 to 0x38000000 (380 MB)
単体テスト test_memory_layout.rs 全件
PASS、make all クリーン、実機・QEMU ともに正常起動。