[{"data":1,"prerenderedAt":1020},["ShallowReactive",2],{"content:\u002Fja\u002Ffiddling\u002Fgo-os":3,"series:content_ja":302},{"id":4,"title":5,"authorship":6,"body":7,"categories":269,"date":271,"description":272,"draft":273,"extension":274,"image":275,"meta":276,"navigation":278,"path":279,"permalink":280,"published":280,"readingTime":281,"recommend":280,"references":280,"seo":286,"seoDescription":287,"seoTitle":288,"sitemap":289,"stem":293,"tags":294,"type":300,"__hash__":301},"content_ja\u002Fposts\u002Ffiddling\u002Fgo-os.md","失敗に終わったプロジェクト：楽しくなかった春節の7日間","human-only",{"type":8,"value":9,"toc":262},"minimark",[10,14,31,52,55,58,62,65,68,75,78,86,89,104,107,116,127,130,140,143,151,154,157,160,166,169,177,184,187,195,198,206,209,212,215,218,221,229,232,244,250,256,259],[11,12,13],"h3",{"id":13},"きっかけ",[15,16,17,18,25,26,30],"p",{},"春節の帰省で乗った高速鉄道の中、知乎の",[19,20,24],"a",{"href":21,"rel":22},"https:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F265806072",[23],"nofollow","Goプログラムをベアメタルで動かす","という記事を読みました。システムインターフェースを実装し直して、Goプログラムのシステムコールや割り込みを引き受ける発想です。とても面白いと思いました。著者はGoでx86 OSの",[19,27,29],{"href":21,"rel":28},[23],"eggos","も作っていて、かなりの完成度です。ランタイムを下から改造しているのでユーザープログラムは意識せずに済み、Goのサードパーティーライブラリもそのまま使えます。TCP\u002FIPスタックまであり、ネットワークライブラリも動きます。読んでいて胸が高鳴りました。",[15,32,33,34,39,40,45,46,51],{},"先行事例を調べると、ずいぶん前からある発想でした。OSDI 2018には高級言語でOSを実装する利点とコストを論じた論文があり、スライドは",[19,35,38],{"href":36,"rel":37},"https:\u002F\u002Fwww.usenix.org\u002Fsites\u002Fdefault\u002Ffiles\u002Fconference\u002Fprotected-files\u002Fosdi18_slides_cutler.pdf",[23],"こちら","です。近年の実装には、GoでOSを作れることを示す実証用カーネル",[19,41,44],{"href":42,"rel":43},"https:\u002F\u002Fgithub.com\u002Fgopher-os\u002Fgopher-os",[23],"gopher-os","があります。MITの博士論文プロジェクト",[19,47,50],{"href":48,"rel":49},"https:\u002F\u002Fgithub.com\u002Fmit-pdos\u002Fbiscuit",[23],"Biscuit","はコンパイラを改造してベアメタルへ出力します。こちらはより完成度が高く、POSIXの一部に対応し、Redisやnginxまで動きます。",[15,53,54],{},"調べるうちに、すべてx86向けという共通点に気づきました。私は以前、Cで小さなRISC-Vカーネルを書いたことがあります。RISC-Vのアセンブリや各種の仕組みはシンプルで、書いていて気持ちがよいものです。そこで、GoでRISC-VのOSを作ろうと思いました。",[15,56,57],{},"思い立ったら即行動。帰省した翌日から始めました。",[11,59,61],{"id":60},"とにかく作る","とにかく作る！",[15,63,64],{},"プロジェクトで大事なのは、名前を付けることです。いや、冗談ですが。",[15,66,67],{},"でも、実際に最初に思いついたのは最高の名前でした。gooseです。",[15,69,70],{},[71,72],"img",{"alt":73,"src":74},"README","https:\u002F\u002Fblog-img.774352199.xyz\u002F2025\u002F736f6c389e54c1327775f1aa95dad597.png",[15,76,77],{},"これは天才的でしょう！",[15,79,80,81,85],{},"まずGoは64ビットRISC-V実行ファイルへのクロスコンパイルに標準対応しています。go buildの前に",[82,83,84],"code",{"code":84},"GOOS=linux GOARCH=riscv64","を付けるだけで、便利です。",[15,87,88],{},"仮想マシンはいつものQEMU、プラットフォームもvirtです。メモリ配置は0x80000000以上が物理RAM、それ未満がMMIOです。後者は機器のメモリがマップされ、そこを操作すると機器を操作することになります。virtの起動時はPCが0x80000000になります。",[15,90,91,92,95,96,99,100,103],{},"一方、通常のGo実行ファイルはユーザー空間の仮想アドレスで動くので、入口は0x10000付近の低いアドレスです。幸い、GoにはTEXTセグメントの開始を指定するリンクフラグ",[82,93,94],{"code":94},"-T","があり、コード全体を高いアドレスに置けます。",[82,97,98],{"code":98},"-E","で入口シンボルも指定できるので、Goの起動処理を引き受ける関数を書けます。Goの入口はmainではなく、初期化を行う",[82,101,102],{"code":102},"_entry","です。",[15,105,106],{},"ただし重大な問題が残ります。入口関数は指定できても、その関数の開始アドレスは指定できません。0x80000000へ配置できなければ、virt起動時にそこに何のコードがあるか分かりません。Cならリンカースクリプトで入口のアドレスを1行指定するだけです。しかし相手はGoです。",[15,108,109,110,115],{},"調べて",[19,111,114],{"href":112,"rel":113},"https:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F69111979\u002Fusing-custom-linker-script-with-go-build",[23],"Stack Overflowの質問","を見つけました。内蔵リンカーではなく外部リンカーを使えばスクリプトを指定できるそうです。ただ試すと現実的ではありません。Goの実行ファイルにはtext、bss、rodata、data以外にも独自のいろいろなセクションがあり、すべてスクリプトで明示する必要があります。ほぼ無理でした。",[15,117,118,119,122,123,126],{},"そこで方針転換です。入口をCで書き、Goの入口を動的に調べて飛べばよさそうです。入口情報はELFファイルにしかなく、ロード後のメモリ像にはありません。ならばELF全体をバイナリとしてCプログラムのdataへ埋め込みます。始点と終点を",[82,120,121],{"code":121},"_binary_kernel_elf_start","、",[82,124,125],{"code":125},"_binary_kernel_elf_end","と名付ければ、Cからすぐ見つけられます。C側はそのELFを解析し、各ロード対象セグメントを対応するアドレスへコピーして、ELFが指定する入口へ飛びます。",[15,128,129],{},"入口のアセンブリは次のとおりです。スタックを設定してC関数へ飛び、dataの2つのシンボルの間にコンパイル済みGo実行ファイルを埋め込みます。",[131,132,138],"pre",{"className":133,"code":135,"language":136,"meta":137},[134],"language-asm","    .section .text.entry\n    .globl _start\n    # 仅仅是设置了 sp 就跳转到 main\n_start:\n    la sp, bootstacktop\n    call bootmain\n\n# 启动线程的内核栈 bootstack 放置在 bss 段的 stack 标记处\n    .section .bss.stack\n    .align 12\n    .global bootstack\nbootstack:\n    # 以下 16K 字节的空间作为 OS 的启动栈\n    .space 0x4000\n    .global bootstacktop\nbootstacktop:\n\n    .section .data\n    .globl _binary_kernel_elf_start\n    .globl _binary_kernel_elf_end\n_binary_kernel_elf_start:\n    .incbin \"kernel.elf\"\n_binary_kernel_elf_end:\n","asm","",[82,139,135],{"__ignoreMap":137},[15,141,142],{},"C関数bootmainも単純です。ELFとプログラムヘッダーテーブルを読み、各セグメントを必要な物理メモリへロードします。",[131,144,149],{"className":145,"code":147,"language":148,"meta":137},[146],"language-c","void\nbootmain()\n{\n    struct elfhdr *elf;\n    struct proghdr *ph, *eph;\n    void (*entry)(void);\n    uchar *pa;\n \n    elf = (struct elfhdr *)(_binary_kernel_elf_start);\n \n    if (elf->magic != ELF_MAGIC)\n        return;\n \n    ph = (struct proghdr *)((uchar *)elf + elf->phoff);\n    eph = ph + elf->phnum;\n    for (; ph \u003C eph; ph++)\n    {\n        pa = (uchar *)ph->paddr;\n        readseg(pa, ph->filesz, ph->off);\n        if (ph->memsz > ph->filesz)\n            clearMem(pa + ph->filesz, ph->memsz - ph->filesz);\n    }\n \n    entry = (void (*)(void))(elf->entry);\n    entry();\n}\n","c",[82,150,147],{"__ignoreMap":137},[15,152,153],{},"最後のentryはELFヘッダーから読んだGoの入口関数のアドレスです。そこへ飛ぶだけです。",[15,155,156],{},"Go側の入口rt0はアセンブリ関数です。Goが使うのは古のOS、Plan 9に由来するPlan 9アセンブリです。複数の命令セットに対応しますが、各アーキテクチャで使える命令を示す公式資料がなぜか見つかりません。例の大半がx86なのでそちらは多少情報があるものの、RV64は跡形もなく、完全に勘頼みでした。",[15,158,159],{},"試行錯誤の末、ようやく入口を書けました。",[131,161,164],{"className":162,"code":163,"language":136,"meta":137},[134],"#include \"textflag.h\"\n\nTEXT ·rt0(SB),NOSPLIT|NOFRAME,$0\n    CALL ·kernelStackTop(SB)\n    MOV  0(SP), A1\n    MOV  A1, SP\n    CALL ·kmain(SB)\n    UNDEF\n    RET\n",[82,165,163],{"__ignoreMap":137},[15,167,168],{},"この書式もなかなか異様です。やることは同じで、kernelStackTopから確保済みスタックのトップのアドレスを取得し、SPをそこへ向けてGo側のkmainを呼びます。唯一のGoファイルも簡単です。",[131,170,175],{"className":171,"code":173,"language":174,"meta":137},[172],"language-go","type stack [16 * 4096]byte\n\ntype virtualAddress uintptr\n\nvar (\n    kstack stack\n)\n\n\u002F\u002Fgo:nosplit\nfunc (s *stack) top() virtualAddress {\n    stackTop := uintptr(unsafe.Pointer(&s[0])) + unsafe.Sizeof(*s)\n    \u002F\u002F Align to 16 bytes.\n    stackTop = stackTop &^ 0xf\n    return virtualAddress(stackTop)\n}\n\n\u002F\u002Fgo:nosplit\nfunc kernelStackTop() uint64 {\n    return uint64(kstack.top())\n}\n\n\u002F\u002Fgo:nosplit\nfunc rt0()\n\n\u002F\u002Fgo:nosplit\nfunc kmain() {\n    for {\n    }\n}\n","go",[82,176,173],{"__ignoreMap":137},[15,178,179,180,183],{},"stack配列をカーネルスタックとして先に確保し、kmainは無限ループするだけです。各関数には",[82,181,182],{"code":182},"\u002F\u002Fgo:nosplit","が付き、スタックオーバーフロー検査の挿入を止めています。さらにGCチェックポイントの挿入を防ぐ暗黙の役割もあります。何も実装していないベアメタル環境ではGCは動かせません。そもそもGCはカーネルでなく、主にユーザー空間のヒープを扱うものですが。",[15,185,186],{},"Makefileはこう書けます。",[131,188,193],{"className":189,"code":191,"language":192,"meta":137},[190],"language-make","Image: kernel.elf\n    $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c boot\u002Fboot.c\n    $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c boot\u002Fboot_header.S\n    $(LD) $(LDFLAGS) -T image.ld -o Image boot.o boot_header.o\n\nkernel.elf:\n    GOOS=linux GOARCH=riscv64 go build -o kernel.elf -ldflags '-E goose\u002Fkernel.rt0 -T 0x80200000' -gcflags \"-N -l\" .\u002Fkmain\n","make",[82,194,191],{"__ignoreMap":137},[15,196,197],{},"kernel.elfではGoのELFを作り、入口をgoose\u002Fkernel.rt0、TEXTの開始を0x80200000にします。Imageは前述のカーネル読み込みコードをビルドします。image.ldでは入口関数をTEXTの先頭に置き、TEXT自体を0x80000000に配置します。",[131,199,204],{"className":200,"code":202,"language":203,"meta":137},[201],"language-plain","\u002F* 执行入口 *\u002F\nENTRY(_start)\n\n\u002F* 数据存放起始地址 *\u002F\nBASE_ADDRESS = 0x80000000;\n\nSECTIONS\n{\n    \u002F* . 表示当前地址（location counter） *\u002F\n    . = BASE_ADDRESS;\n\n    \u002F* start 符号表示全部的开始位置 *\u002F\n    kernel_start = .;\n\n    text_start = .;\n\n    \u002F* .text 字段 *\u002F\n    .text : {\n        \u002F* 把 entry 函数放在最前面 *\u002F\n        *(.text.entry)\n        \u002F* 要链接的文件的 .text 字段集中放在这里 *\u002F\n        *(.text .text.*)\n    }\n    ...\n}\n","plain",[82,205,202],{"__ignoreMap":137},[15,207,208],{},"よし！",[15,210,211],{},"あまりに夢中で、春節中の親戚回りもろくにできませんでした。一日中部屋で資料を集め、外でもぼんやり手法を考えていて、取りつかれたようでした。",[11,213,214],{"id":214},"大失敗",[15,216,217],{},"じゃじゃーん！",[15,219,220],{},"QEMUにカーネルを読み込んでデバッグすると、セグメントをメモリにロードするところで固まっていました。go buildのELFをreadelfで調べたところ、奇妙なものがありました。",[131,222,227],{"className":223,"code":225,"language":226,"meta":137},[224],"language-bash","Type           Offset             VirtAddr           PhysAddr\n                 FileSiz            MemSiz              Flags  Align\n  PHDR           0x0000000000000040 0x00000000801ff040 0x00000000801ff040\n                 0x0000000000000188 0x0000000000000188  R      0x10000\n  NOTE           0x0000000000000f9c 0x00000000801fff9c 0x00000000801fff9c\n                 0x0000000000000064 0x0000000000000064  R      0x4\n  LOAD           0xffffffffffff1000 0x00000000801f0000 0x00000000801f0000\n                 0x0000000000063300 0x0000000000063300  R E    0x10000\n  LOAD           0x0000000000060000 0x0000000080260000 0x0000000080260000\n                 0x000000000006adb8 0x000000000006adb8  R      0x10000\n  ...\n","bash",[82,228,225],{"__ignoreMap":137},[15,230,231],{},"3つ目のOffsetが0xffffffffffff1000という巨大な値です。Offsetはファイル先頭からセグメント内容までの位置ですが、このELFは数十KBしかありません。こんなオフセットがどこから出るのでしょう。メモリに載せてもvirtの標準RAMは128MBなので、即座に破綻します。",[15,233,234,235,237,238,243],{},"分からずに実験した結果、リンク引数",[82,236,94],{"code":94},"を付けると必ず起きると判明しました。しかし省くこともできません。低アドレスはMMIOなので、そこにロードできないからです。GoのGitHubに",[19,239,242],{"href":240,"rel":241},"https:\u002F\u002Fgithub.com\u002Fgolang\u002Fgo\u002Fissues\u002F57983",[23],"cmd\u002Flink: wrong program header offset when cross-compile to riscv64 when setting -T text alignment","を立て、状況を説明すると次の返事が来ました。",[15,245,246],{},[71,247],{"alt":248,"src":249},"ISSUE","https:\u002F\u002Fblog-img.774352199.xyz\u002F2025\u002F42c633b821d4323697e542b47a8fce31.png",[15,251,252,253,255],{},"どうやらRV64の",[82,254,94],{"code":94},"対応が不完全なようです……。",[15,257,258],{},"こうしてプロジェクトは今まで棚上げです。せっかくのいい名前がもったいない \u002F(ㄒo ㄒ)\u002F Go公式の修正を待つしかありませんが、RV64にはあまり力が入っていない気もします。RV64への標準クロスコンパイルがメインラインに入ったのも、ここ数年ですし……。",[15,260,261],{},"腹が立つので、Rustに行きます！",{"title":137,"searchDepth":263,"depth":263,"links":264},4,[265,267,268],{"id":13,"depth":266,"text":13},3,{"id":60,"depth":266,"text":61},{"id":214,"depth":266,"text":214},[270],"fiddling","2023-02-02 23:24:55","春節の帰省列車で、Goをベアメタルで動かす記事を読み、低レベルのシステムインターフェースに興味が湧きました。実際に動く実装を見て、高級言語でOSを作る可能性に胸が躍ります。関連研究を調べると先行例も見つかり、積もった熱意は期待に満ちたプロジェクトへと変わりました。しかし、最後は思いどおりにはいきませんでした。",false,"md","https:\u002F\u002Fblog-img.774352199.xyz\u002FxB1Ni5.webp",{"slots":277},{},true,"\u002Ffiddling\u002Fgo-os",null,{"text":282,"minutes":283,"time":284,"words":285},"12 min read",11.81,708600,2362,{"title":5,"description":272},"GoでRISC-Vカーネルgooseを作ろうとした春節の記録。CによるELFロードとアセンブリの入口を実装し、最後は-T指定によるリンカーのオフセット異常で開発を中断しました。","Go のベアメタル実行と RISC-V カーネル：リンカー問題の調査",{"loc":279,"images":290},[291,292],{"loc":74},{"loc":249},"posts\u002Ffiddling\u002Fgo-os",[295,296,297,298,299],"Go","RISC-V","オペレーティングシステム","ベアメタルプログラミング","ランタイム","tech","yj-c_YPeTB-Pc6coobz5SAy8ctBQ4xlNKu0BU-n6B10",[303,321,338,355,372,390,407,425,443,459,476,492,496,512,529,547,562,579,593,610,628,645,660,677,693,712,729,746,764,778,796,814,830,845,859,876,891,906,921,935,949,963,978,992,1006],{"categories":304,"date":306,"description":307,"image":308,"path":309,"readingTime":310,"recommend":280,"tags":315,"title":320,"type":300},[305],"daily","2024-09-01 22:03:10","子どもの頃からの胃腸の不調が大学時代には不思議と消えたものの、就職後の夜更かしと飲酒で再発。慢性胃炎との付き合いは一筋縄ではいきませんでした。吐き気や胃のむかつきが日常になり、何度か検査を受けて生活を振り返るうちに、ようやく腰を据えて治療に向き合うようになりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002F0Hr9l5.webp","\u002Fdaily\u002Fanti-chronic-gastritis",{"text":311,"minutes":312,"time":313,"words":314},"7 min read",6.485,389100,1297,[316,317,318,319],"慢性胃炎","受診記録","胃内視鏡検査","健康記録","慢性胃炎の治療記録",{"categories":322,"date":323,"description":324,"image":325,"path":326,"readingTime":327,"recommend":280,"tags":332,"title":337,"type":300},[305],"2022-04-11 00:13:13","『三体』では、劉慈欣が壮大な歴史を通して個人と集団の関係を描いています。西側の民主主義への疑念と、大多数の人々に運命を委ねることへの悲観が、三部作を貫いています。英雄たちが力を尽くしても、その努力は歴史の流れに押し流される。文化大革命から始まる物語に、少数の傑出した人物と平凡な大衆の対立を読み、人間性と社会について考えました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FLTzbFP.webp","\u002Fdaily\u002Fpeople-in-three-body",{"text":328,"minutes":329,"time":330,"words":331},"19 min read",18.495,1109700,3699,[333,334,335,336],"三体","劉慈欣","SF文学","読書ノート","『三体』における「大多数の人々」",{"categories":339,"date":340,"description":341,"image":342,"path":343,"readingTime":344,"recommend":280,"tags":349,"title":354,"type":300},[305],"2024-01-04 02:06:51","2024年の学習目標は、日本語をN2レベルに引き上げること、SICPとTAPLを最後までやり切ること、POSIXを完全に実装したカーネルを作ること、そしてブログのテーマを更新すること。どれも簡単ではありませんが、今年取り組む方向は決まりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FV3rSQC.webp","\u002Fdaily\u002Fplan2024",{"text":345,"minutes":346,"time":347,"words":348},"1 min read",0.345,20700,69,[350,351,352,353,297],"年間計画","日本語学習","SICP","TAPL","2024年の学習計画",{"categories":356,"date":357,"description":358,"image":359,"path":360,"readingTime":361,"recommend":280,"tags":366,"title":371,"type":300},[305],"2024-09-28 16:26:00","ByteDanceで働いて3年。変化の速い環境で、時間まで加速したように感じながらも、どうにか心のバランスを保ってきました。杭州のオフィスのベランダから遠くの山を眺めていた入社当初を振り返り、仕事の壁や心境の変化、忙しさの中で自分のペースを探してきた日々を記します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhnCaht.webp","\u002Fdaily\u002Fwork-for-3-years",{"text":362,"minutes":363,"time":364,"words":365},"20 min read",19.73,1183800,3946,[367,368,369,370],"ByteDance","エンジニアのキャリア","仕事の振り返り","メンタルヘルス","ByteDanceで3年働きながら、ある程度の正気を保つことも不可能ではない",{"categories":373,"date":374,"description":375,"image":376,"path":377,"readingTime":378,"recommend":280,"tags":383,"title":389,"type":300},[270],"2025-05-28 22:09:00","ブログをAstroに移行したところ、従来のGoogle Analytics導入方法では性能面が気になるようになりました。headタグにJavaScriptを直接追加してイベントを送ることはできますが、ページの性能に影響します。そこでpartytownでスクリプトをメインスレッドから切り離し、読み込みを妨げないようにしました。サンプルコードに手を加えることでGoogle Analyticsの導入に成功し、性能とアクセス解析を両立できました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FQ0w4RN.webp","\u002Ffiddling\u002Fastro-google-tag-manager",{"text":379,"minutes":380,"time":381,"words":382},"4 min read",3.455,207300,691,[384,385,386,387,388],"Astro","Google Analytics","Google Tag Manager","Partytown","アクセス解析","AstroにGoogle Analyticsを導入する（Tag Manager編）",{"categories":391,"date":392,"description":393,"image":394,"path":395,"readingTime":396,"recommend":401,"tags":402,"title":406,"type":300},[270],"2023-04-08 13:16:36","新しいプログラミング言語の設計は、難しくも面白い作業です。複雑なコンパイラ理論や機能の実装詳細をいったん脇に置き、コードがコンピューターのどこで動くかに注目すると、言語の作り方が見えてきます。RISC-VI命令セットを出発点に、基盤となる構造、階層化されたシステム、仮想マシンのモデルをたどり、言語の本質を考えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FuO420B.webp","\u002Ffiddling\u002Fchitchat-about-programming-language",{"text":397,"minutes":398,"time":399,"words":400},"28 min read",27.03,1621800,5406,2,[403,404,405,296],"プログラミング言語設計","型システム","コンパイラ設計","プログラミング言語についての雑談",{"categories":408,"date":409,"description":410,"image":411,"path":412,"readingTime":413,"recommend":263,"tags":418,"title":424,"type":300},[270],"2025-04-18 16:43:12","彼女が仕事で北京から上海に引っ越したので、回線の手配も手伝いました。ところが上海電信の500Mは杭州の1000Mより高く、なんとも納得がいきません。そこで上海での透過プロキシ、特定の通信の杭州経由での外部接続、両拠点のLAN相互接続を目指してネットワークを組むことにしました。杭州側はソフトウェアルーターと無線APのシンプルな構成で、普段から自宅経由で通信できる環境があり、次の挑戦に向けた準備はできています。","https:\u002F\u002Fblog-img.774352199.xyz\u002FO6cAGh.webp","\u002Ffiddling\u002Fcross-city-network-setup",{"text":414,"minutes":415,"time":416,"words":417},"11 min read",10.14,608400,2028,[419,420,421,422,423],"Tailscale","mihomo","拠点間ネットワーク","透過プロキシ","ホームネットワーク","上海と杭州の自宅ネットワークをつなぐ",{"categories":426,"date":427,"description":428,"image":429,"path":430,"readingTime":431,"recommend":280,"tags":436,"title":442,"type":300},[270],"2021-12-27 00:09:00","CSAPPの学習では実験が欠かせませんが、Linux環境の構築が壁になりがちです。とくに仮想マシンでは、インストール失敗、互換性、ネットワーク接続などの問題に悩まされます。Windows 10バージョン2004以降なら、WSL（Windows Subsystem for Linux）が有力な選択肢です。従来の仮想マシンの複雑さや性能面の負担を避けながら、Linux環境を手軽に利用できます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FvqOC7N.webp","\u002Ffiddling\u002Fcsapplab0",{"text":432,"minutes":433,"time":434,"words":435},"10 min read",9.585,575100,1917,[437,438,439,440,441],"CSAPP","WSL2","Linux","GDB","実験環境","CSAPP Labの環境構築",{"categories":444,"date":445,"description":446,"image":447,"path":448,"readingTime":449,"recommend":280,"tags":454,"title":458,"type":300},[270],"2024-07-13 17:49:00","Debianをサイドルーターに使うと、OpenWrtやLuCIに依存せず、より安定した柔軟な構成を作れます。Debianを直接設定することでシステムを細かく制御でき、GUIの制約や不安定さを避けられます。一般的なサイドルーター構成と比べて透過プロキシを安定して運用しやすく、性能や効率を重視する場合の選択肢になります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FpPRU5x.webp","\u002Ffiddling\u002Fdebian-as-bypass-router",{"text":450,"minutes":451,"time":452,"words":453},"18 min read",17.525,1051500,3505,[455,456,420,457,422],"Debian","サイドルーター","AdGuard Home","Debianをサイドルーターにする",{"categories":460,"date":461,"description":462,"image":463,"path":464,"readingTime":465,"recommend":280,"tags":470,"title":475,"type":300},[270],"2024-08-16 23:53:00","FakeIPを使った透過プロキシ構成で、従来のサイドルーターの単一障害点、性能不足、複雑なポート転送を改善します。プロキシコアをsing-boxに変えることで、転送性能を高めながら設定も簡単にできます。対応プロトコルが豊富で、従来のClashより最適化も進んでいます。同じ構成はClashでも実現できますが、sing-boxは柔軟な選択肢になります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FS2HHD5.webp","\u002Ffiddling\u002Ffake-ip-based-transparent-proxy",{"text":466,"minutes":467,"time":468,"words":469},"14 min read",13.1,786000,2620,[471,472,422,473,474],"FakeIP","sing-box","ポリシーベースルーティング","トラフィック振り分け","FakeIPを使った透過プロキシの振り分け",{"categories":477,"date":478,"description":479,"image":480,"path":481,"readingTime":482,"recommend":280,"tags":487,"title":491,"type":300},[270],"2024-08-15 23:50:00","サイドルーターを導入すると、メインルーターのポート転送が効かなくなることがあります。ゲートウェイをサイドルーターに変えることで通信経路が変わり、メインルーターを前提とした転送が正常に動かなくなるためです。ゲートウェイはアドレスを変換して内部ネットワークの通信を外部へ転送し、各端末は外部との通信にこれを必要とします。この仕組みを理解すると、ポート転送の問題を解決しやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FmRqws9.webp","\u002Ffiddling\u002Ffix-port-forward-in-bypass-router",{"text":483,"minutes":484,"time":485,"words":486},"6 min read",5.155,309300,1031,[456,488,489,490],"ポート転送","NAT","ネットワークのトラブルシューティング","サイドルーター環境でポート転送が効かない問題を解決する",{"categories":493,"date":271,"description":272,"image":275,"path":279,"readingTime":494,"recommend":280,"tags":495,"title":5,"type":300},[270],{"text":282,"minutes":283,"time":284,"words":285},[295,296,297,298,299],{"categories":497,"date":498,"description":499,"image":500,"path":501,"readingTime":502,"recommend":280,"tags":507,"title":511,"type":300},[270],"2022-08-15 01:05:01","システムのリファクタリングで、階層ごとのエンティティ変換に苦労しました。ビュー層の商品VO、ドメイン層のentity、永続化層のPOは似ていても、型のわずかな違いで直接変換できず、ディープコピーが面倒になります。そこでリフレクションを使った汎用的な変換処理を実装し、大量のassemblerメソッドを減らして、保守性と柔軟性を高めることにしました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBlhm0I.webp","\u002Ffiddling\u002Fgolang-deepcopy-between-different-type",{"text":503,"minutes":504,"time":505,"words":506},"5 min read",4.14,248400,828,[295,508,509,510],"リフレクション","ディープコピー","構造体変換","Goで異なる型の構造体をディープコピーする",{"categories":513,"date":514,"description":515,"image":516,"path":517,"readingTime":518,"recommend":280,"tags":522,"title":528,"type":300},[270],"2025-03-31 23:51:00","Appleヘルスケアの心拍数を定期的にサーバーへ同期し、Grafanaで可視化して直感的に確認できるようにしました。Health Auto ExportのREST API機能でHTTPエンドポイントへデータを送り、InfluxDBに保存します。Grafanaのダッシュボードから、自分の心拍数の変化を追ったり分析したりできます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FF4qD2T.webp","\u002Ffiddling\u002Fheart-rate-to-grafana",{"text":379,"minutes":519,"time":520,"words":521},3.76,225600,752,[523,524,525,526,527],"Apple Watch","Health Auto Export","InfluxDB","Grafana","心拍数モニタリング","My Heart Beats for U：心拍数をGrafanaで可視化する",{"categories":530,"date":531,"description":532,"image":533,"path":534,"readingTime":535,"recommend":539,"tags":540,"title":546,"type":300},[270],"2025-06-10 20:18:00","macOSとiPadOS 26では、新しいデザイン言語Liquid Glassが導入され、アイコンやウインドウの印象が一新されました。とくにiPadのアプリをウインドウで扱えるようになったことは、生産性向上のための端末へ進む大きな一歩です。一方、透明なコントロールセンターやLaunchpadの統合には賛否があり、使い勝手には改善の余地もあります。課題はありつつも、今後につながる更新だと感じました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FTPSaLE.webp","\u002Ffiddling\u002Fmacos-26-trial",{"text":311,"minutes":536,"time":537,"words":538},6.94,416400,1388,5,[541,542,543,544,545],"macOS 26","iPadOS 26","Liquid Glass","Apple Intelligence","OS使用感","macOS 26とiPadOS 26を試してみた",{"categories":548,"date":549,"description":550,"image":551,"path":552,"readingTime":553,"recommend":280,"tags":557,"title":561,"type":300},[270],"2026-06-11 10:00:00","今年もWWDCでmacOS 27の新しいApple Intelligenceが登場しました。macOS 26時代の回避方法はもう使えず、引き続きAppleとの知恵比べです。","https:\u002F\u002Fblog-img.774352199.xyz\u002FfOFucm.webp","\u002Ffiddling\u002Fmacos-27-apple-intelligence-chatgpt",{"text":432,"minutes":554,"time":555,"words":556},9.74,584400,1948,[558,544,559,560],"macOS 27","ChatGPT","中国本土向けMac","中国本土向けMacでApple Intelligenceを使う：地域変更からChatGPTの取り出しまで",{"categories":563,"date":564,"description":565,"image":566,"path":567,"readingTime":568,"recommend":280,"tags":572,"title":578,"type":300},[270],"2025-07-20 23:32:00","MoonTVはNext.jsとReactで作った動画集約プラットフォームで、連続ドラマなどを手軽に楽しむためのものです。LibreTVを改善しようとしたことが始まりで、数か月の開発を経て多くの関心と利用を集めています。Cursorのおかげで効率よく開発できた一方、複数環境への対応や複雑なデータ依存関係には苦労しました。ユーザーが増える中、フィードバックを受けて改善を続けています。","https:\u002F\u002Fblog-img.774352199.xyz\u002FnIeONi.webp","\u002Ffiddling\u002Fmoontv-vibe-coding",{"text":414,"minutes":569,"time":570,"words":571},10.98,658800,2196,[573,574,575,576,577],"MoonTV","LunaTV","Vibe Coding","Cursor","AI支援開発","MoonTV：Vibe Codingを試してみた",{"categories":580,"date":581,"description":582,"image":583,"path":584,"readingTime":585,"recommend":280,"tags":589,"title":592,"type":300},[270],"2024-10-07 16:51:00","BGPをもとに中国国内・国外のIPを振り分けることで、透過プロキシの効率と精度を高めます。国外の宛先をFakeIPで識別すれば、メインルーターでより適切に通信を振り分けられます。sing-boxのDNS設定も見直し、DNSクエリを柔軟かつ効率的に処理して、ネットワーク全体の使い勝手を改善します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FMOmM1s.webp","\u002Ffiddling\u002Fmore-accurate-chnroute",{"text":483,"minutes":586,"time":587,"words":588},5.75,345000,1150,[590,591,473,474],"BGP","IPアドレスデータベース","BGPで中国国内・国外IPの振り分けをより正確にする",{"categories":594,"date":595,"description":596,"image":597,"path":598,"readingTime":599,"recommend":280,"tags":604,"title":609,"type":300},[270],"2025-12-14 14:31:00","友人の一言からシミュレーターに興味が湧き、Microsoft Flight Simulatorを購入。地図やモデルはリアルタイム配信、アカウントは再ログインが必要、チュートリアルは見つけにくく、キーボード操作も難しい。結局フライトスティックを買い、Pico VRまで設定してようやく一通り体験できました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FlfhEuE.webp","\u002Ffiddling\u002Fmsfs2024-joystick-and-pico",{"text":600,"minutes":601,"time":602,"words":603},"9 min read",8.96,537600,1792,[605,606,607,608],"Microsoft Flight Simulator 2024","Thrustmaster TCA","PICO VR","フライトシミュレーション","Microsoft Flight Simulator 2024をあれこれ試す",{"categories":611,"date":612,"description":613,"image":614,"path":615,"readingTime":616,"recommend":280,"tags":621,"title":627,"type":300},[270],"2025-06-05 23:26:00","OnePlusからiPhoneへと何度も機種変更するうち、いじる楽しさからエコシステムへの依存へと関心が変わりました。最近、彼女の一言をきっかけに写真を改善しようとOPPO Find X8 Ultraを購入。Apple環境からの移行では、Androidアプリの質のばらつきと代替探しの難しさを改めて感じました。1か月をかけて、異なるプラットフォームの摩擦に折り合いをつけた記録です。","https:\u002F\u002Fblog-img.774352199.xyz\u002F19NIhZ.webp","\u002Ffiddling\u002Fone-month-using-android",{"text":617,"minutes":618,"time":619,"words":620},"15 min read",14.05,843000,2810,[622,623,624,625,626],"Android","OPPO","iOS","スマートフォン使用感","エコシステム移行","Androidに乗り換えて1か月",{"categories":629,"date":630,"description":631,"image":632,"path":633,"readingTime":634,"recommend":280,"tags":638,"title":644,"type":300},[270],"2026-05-11 22:43:00","GitHub Trendingで旅行計画ツールを見つけ、自分でも動かしたくなりました。どうせ新しいVPSを借りるなら、ついでにもう少し、いや、だいぶ色々入れてしまおうと。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBBdDWW.webp","\u002Ffiddling\u002Fone-trek-twenty-stacks",{"text":414,"minutes":635,"time":636,"words":637},10.34,620400,2068,[639,640,641,642,643],"TREK","Docker Compose","Dockge","VPS","セルフホスティング","TREKひとつのつもりが、20個のスタックに",{"categories":646,"date":647,"description":648,"image":649,"path":650,"readingTime":651,"recommend":280,"tags":655,"title":659,"type":300},[270],"2025-01-16 23:09:00","OPNsenseは、美しい画面と充実した機能を備えるオープンソースのファイアウォール・ルーターです。いくつかの構成を試した末に、透過プロキシやトラフィック振り分けでの可能性に気づきました。BGPベースの振り分けと組み合わせることで安全性と安定性を高められ、IPリストの自動更新で管理もしやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FxA8C1E.webp","\u002Ffiddling\u002Fopnsense-transparent-proxy",{"text":282,"minutes":652,"time":653,"words":654},11.38,682800,2276,[656,657,420,658,422,474],"OPNsense","FreeBSD","tun2socks","OPNsenseで透過プロキシとトラフィック振り分けを実現する",{"categories":661,"date":662,"description":663,"image":664,"path":665,"readingTime":666,"recommend":266,"tags":670,"title":676,"type":300},[270],"2025-03-15 20:35:00","構文解析では、ユーザー定義型名と通常の変数名を見分けることが課題になります。たとえば`a*b;`は算術式とも宣言とも解釈できます。とくに型指定子に関する文法規則によって変数名が型名と解釈され、正確さや読みやすさに影響します。初期化を伴わない変数宣言は多いため、この曖昧さはソースコードの随所に現れます。","https:\u002F\u002Fblog-img.774352199.xyz\u002F2VKHK9.webp","\u002Ffiddling\u002Fparser-type-variable-ambiguity",{"text":466,"minutes":667,"time":668,"words":669},13.58,814800,2716,[671,672,673,674,675],"構文解析","GLR","シンボルテーブル","スコープ","曖昧性解消","構文解析で型名と変数名の曖昧さを解消する",{"categories":678,"date":679,"description":680,"image":681,"path":682,"readingTime":683,"recommend":280,"tags":687,"title":692,"type":300},[270],"2023-05-24 17:51:09","RISC-Vツールチェーンをインストールするには、まずriscv-gnu-toolchainのソースを取得します。clone時に`--depth=1`を付けるとダウンロード量を減らせます。READMEのPrerequisitesを確認し、必要な依存関係をそろえてから進めます。Debianではコマンドで依存パッケージをまとめて導入できます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FrWNOKx.webp","\u002Ffiddling\u002Fspike-install",{"text":379,"minutes":684,"time":685,"words":686},3.89,233400,778,[296,688,689,690,691],"Spike","riscv-pk","クロスコンパイル","ツールチェーン","RISC-Vツールチェーンとエミュレーターのインストール",{"categories":694,"date":695,"description":696,"image":697,"path":698,"readingTime":699,"recommend":703,"tags":704,"title":711,"type":300},[270],"2026-09-09 23:59:00","これも一種のNTRですよね","https:\u002F\u002Fblog-img.774352199.xyz\u002FNDPUwc.webp","\u002Ffiddling\u002Fsteamdeck-switch-60fps",{"text":466,"minutes":700,"time":701,"words":702},13.905,834300,2781,7,[705,706,707,708,709,710],"Steam Deck","Nintendo Switch","EmuDeck","Eden","Lossless Scaling","フレーム生成","Steam Deckの第二の人生：Switchエミュレーター導入からフレーム補間で60FPSまで",{"categories":713,"date":714,"description":715,"image":716,"path":717,"readingTime":718,"recommend":280,"tags":723,"title":728,"type":300},[270],"2024-06-23 15:31:32","GFWは単に出口のゲートウェイを監視するのではなく、通信経路の脇から国際通信を傍受します。出入国するIPパケットをクラスタへ複製し、詳しく分析・フィルタリングする仕組みです。どこで何をしているかを理解することは、検閲回避の検討に欠かせません。ネットワーク構成を調べることで、遮断の経路や技術、対処方法が見えてきます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FsOpJuL.webp","\u002Ffiddling\u002Ftech-about-gfw",{"text":719,"minutes":720,"time":721,"words":722},"25 min read",24.975,1498500,4995,[724,725,726,727],"GFW","DNSポイズニング","TCP","インターネット検閲","GFWの仕組みを探る",{"categories":730,"date":731,"description":732,"image":733,"path":734,"readingTime":735,"recommend":280,"tags":739,"title":745,"type":300},[270],"2022-04-16 00:01:28","Javaでは`this`を使うことで、コンパイラの定数最適化が効かなくなる場合があります。このコード例の`ab1`と`ab2`は同じstatic final変数`s`を参照しているように見えますが、比較結果は異なります。静的変数を直接参照して文字列を連結する`ab1`に対し、`this`経由の`ab2`では同じ定数伝播の最適化が行われません。わずかな構文の違いが、コンパイル結果を変える例です。","https:\u002F\u002Fblog-img.774352199.xyz\u002FgKtkYe.webp","\u002Ffiddling\u002Fthis-in-javac-string-concat",{"text":379,"minutes":736,"time":737,"words":738},3.88,232800,776,[740,741,742,743,744],"Java","javac","文字列連結","定数伝播","バイトコード","Javaのthisキーワードでコンパイル時の定数伝播が効かなくなる問題",{"categories":747,"date":748,"description":749,"image":750,"path":751,"readingTime":752,"recommend":280,"tags":757,"title":763,"type":300},[270],"2025-01-29 21:58:00","ひとこと投稿機能があれば、静的ブログの記事公開に伴う手間や心理的な負担を減らし、短い思いつきをいつでも共有できます。Cloudflare Workersでバックエンドを実装し、KVで投稿を保存・管理します。フロントエンドはVitePressにVueコンポーネントを埋め込み、投稿を手軽に表示してブログに動きと交流の場を加えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhZX6hr.webp","\u002Ffiddling\u002Fvitepress-memos-component",{"text":753,"minutes":754,"time":755,"words":756},"24 min read",23.345,1400700,4669,[758,759,760,761,762],"VitePress","Vue","Cloudflare Workers","Cloudflare KV","マイクロブログ","VitePressにひとこと投稿機能を実装する",{"categories":765,"date":766,"description":767,"image":768,"path":769,"readingTime":770,"recommend":280,"tags":774,"title":777,"type":300},[270],"2025-03-15 16:24:00","ある平凡な午後、Telegramの通知で魅力的なVPSプランを見つけました。中国電信CN2直結、帯域2.5Gという好条件です。IPv6付きで動画配信サービスの地域制限解除にも便利ですが、すべての通信をWARP経由にする必要はありません。以前のスクリプトは手軽な一方、速度と振り分けに不満があり、もっと柔軟な方法を探すことにしました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FMcjrrF.webp","\u002Ffiddling\u002Fvps-warp-ipv6",{"text":503,"minutes":771,"time":772,"words":773},4.09,245400,818,[775,776,642,473,474],"Cloudflare WARP","IPv6","VPSの特定の通信をWARP経由のIPv6で外に出す",{"categories":779,"date":780,"description":781,"image":782,"path":783,"readingTime":784,"recommend":788,"tags":789,"title":795,"type":300},[270],"2026-08-17 23:59:21","いじればいじるほど、もっといじりたくなります。年を取ってもまだまだ元気、まだまだ元気です。","https:\u002F\u002Fblog-img.774352199.xyz\u002FqfxB0h.webp","\u002Ffiddling\u002Fxiaomi17-root-and-hide-root",{"text":600,"minutes":785,"time":786,"words":787},8.83,529800,1766,6,[790,791,792,793,794],"Xiaomi 17","Bootloader","Android Root","ファームウェア書き換え","Rootの隠蔽","Xiaomi 17を普段使いに：ロック解除、ROM書き込み、root化とroot隠し",{"categories":797,"date":799,"description":800,"image":801,"path":802,"readingTime":803,"recommend":280,"tags":808,"title":813,"type":300},[798],"notes","2022-01-20 22:29:00","Lab 1では、masterとworkerという2つの主要な部分からなるMapReduceシステムを実装します。GoのRPCと並行プログラミングを十分に使いこなし、MapReduceの処理の流れも深く理解する必要があります。実装は2つの版を作り、mutexでロックする方式から、よりすっきりしたchannelによる明示的なロックを使わない方式へと改めました。後者のほうが設計もシンプルで分かりやすくなっています。実習を理解する鍵は、関連資料、特にフローチャートとその説明をしっかり読むことです。","https:\u002F\u002Fblog-img.774352199.xyz\u002FibVwPJ.webp","\u002Fnotes\u002F65840\u002Fmapreducelab",{"text":804,"minutes":805,"time":806,"words":807},"13 min read",12.39,743400,2478,[809,810,295,811,812],"MIT 6.5840","MapReduce","RPC","並行プログラミング","6.5840 Lab 1：MapReduce",{"categories":815,"date":816,"description":817,"image":818,"path":819,"readingTime":820,"recommend":280,"tags":824,"title":829,"type":300},[798],"2022-01-16 17:32:00","MapReduceは、大規模なデータセットの処理を簡単にするための効率的な並列計算モデルです。利用者はMapとReduceという2つの主要な関数を定義することで、複雑なタスクを簡単な操作に分解できます。データの分配やタスクの割り当てはフレームワークが自動で管理するため、開発者は低レベルの細部に気を取られず、アルゴリズムそのものに集中できます。分散システムで広く使われていることからも、その柔軟性と実用性が分かります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FApIDdC.webp","\u002Fnotes\u002F65840\u002Fmapreducepaper",{"text":600,"minutes":821,"time":822,"words":823},8.085,485100,1617,[810,825,826,827,828],"分散システム","論文ノート","並列計算","耐障害性","MapReduce論文を読む",{"categories":831,"date":832,"description":833,"image":834,"path":835,"readingTime":836,"recommend":280,"tags":840,"title":844,"type":300},[798],"2022-12-16 02:06:10","Lab 2Aでは、Raftのリーダー選出とハートビートを実装し、さまざまな厳しい条件でも任期の交代や選挙が正常に行われるようにします。実習全体は4段階からなり、この後に実装する分散KVストアの土台になります。明示的なロックを使わない設計によって、Raft構造体を簡潔にします。実習の手引きには必要な背景知識が載っていますが、前の実習と比べると参考資料に頼れる部分はほとんどなく、自力で実装することが重視されます。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fc11Uk4.webp","\u002Fnotes\u002F65840\u002Fraftlab2a",{"text":450,"minutes":837,"time":838,"words":839},17.515,1050900,3503,[809,841,295,842,843],"Raft","リーダー選出","分散合意","6.5840 Lab 2A：リーダー選出",{"categories":846,"date":847,"description":848,"image":849,"path":850,"readingTime":851,"recommend":280,"tags":856,"title":858,"type":300},[798],"2022-12-03 21:40:09","Raftは、ログレプリケーションの効率を高めるために設計された合意アルゴリズムです。複数のマシンからなるクラスタに適しており、一部のマシンが故障してもサービスを継続できます。複製状態機械モデルを使い、ログに命令の順序を記録することで、クラスタ内の各マシンが同じ状態に到達できるようにします。論文『In Search of an Understandable Consensus Algorithm』は、Raftの設計思想とPaxosとの比較を詳しく論じ、その理解しやすさを示すとともに、信頼できる大規模なソフトウェアシステムを構築するための土台を提供しています。この記事は、その中心的な概念と応用を理解するための読書メモです。","https:\u002F\u002Fblog-img.774352199.xyz\u002F7mmvIZ.webp","\u002Fnotes\u002F65840\u002Freftextendedpaper",{"text":852,"minutes":853,"time":854,"words":855},"30 min read",29.245,1754700,5849,[841,843,857,826],"ログ複製","Raft論文を読む",{"categories":860,"date":862,"description":863,"image":864,"path":865,"readingTime":866,"recommend":870,"tags":871,"title":875,"type":300},[861],"projects","2021-11-27 14:43:00","MYDBは、データベースの基本原理を学び、実装してみるための個人プロジェクトです。空き時間を使い、半月あまりかけて作りました。大学のデータベースシステムの授業で基礎には触れたものの、インターン中は授業を口実にサボってばかりでした。面接で正直に答えても大きな問題にはなりませんでしたが、それをきっかけに自分の知識を見直し、実際に手を動かして学ぼうと考えるようになりました。そうして生まれたのがこのプロジェクトです。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fxfci2J.webp","\u002Fprojects\u002Fmydb\u002Fmydb0",{"text":600,"minutes":867,"time":868,"words":869},8.03,481800,1606,1,[872,740,873,874],"MYDB","データベース実装","データベースアーキテクチャ","MYDB 0. プロジェクト構成と、先に伝えておきたいこと",{"categories":877,"date":878,"description":879,"image":880,"path":881,"readingTime":882,"recommend":280,"tags":887,"title":890,"type":300},[861],"2021-11-28 16:10:00","MYDBではXIDファイルでトランザクションを管理します。各トランザクションには1から増える一意のXIDがあり、XID 0は常にコミット済みのスーパートランザクションです。TransactionManagerがこのファイルを管理し、実行中・コミット済み・中止済みという3つの状態を記録します。この仕組みにより状態を正確に照会・管理でき、システムの安定性と信頼性を支えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FH4zZAK.webp","\u002Fprojects\u002Fmydb\u002Fmydb1",{"text":883,"minutes":884,"time":885,"words":886},"8 min read",7.42,445200,1484,[872,740,888,889],"トランザクション管理","XID","MYDB 1. まずはシンプルなTMから",{"categories":892,"date":893,"description":894,"image":895,"path":896,"readingTime":897,"recommend":280,"tags":901,"title":905,"type":300},[861],"2021-12-25 18:26:00","MYDBはMySQLに似たC\u002FS構成を採用し、複数のクライアントがソケットでサーバーへ接続してSQLを実行し、結果を受け取れます。通信には専用のバイナリー形式を使いますが、実装を簡単にするならプレーンテキストも選択肢です。サーバーとクライアントの基本的な転送構造によって、データのやり取りと処理を行います。","https:\u002F\u002Fblog-img.774352199.xyz\u002FPAHrUZ.webp","\u002Fprojects\u002Fmydb\u002Fmydb10",{"text":483,"minutes":898,"time":899,"words":900},5.76,345600,1152,[872,740,902,903,904],"Socket","クライアントサーバー構成","通信プロトコル","MYDB 10. サーバー・クライアントの実装と通信プロトコル",{"categories":907,"date":908,"description":909,"image":910,"path":911,"readingTime":912,"recommend":280,"tags":916,"title":920,"type":300},[861],"2021-11-30 23:18:00","データマネージャー（DM）は上位モジュールとファイルシステムをつなぎ、ページとキャッシュを管理しながら、データの安全性と復旧を支えます。キャッシュには従来のLRUではなく参照カウント方式を採用し、汎用性と効率を高めて、この先のデータ操作の土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FWdIGoG.webp","\u002Fprojects\u002Fmydb\u002Fmydb2",{"text":414,"minutes":913,"time":914,"words":915},10.395,623700,2079,[872,740,917,918,919],"参照カウント","キャッシュ設計","共有メモリ","MYDB 2. 参照カウント方式のキャッシュ基盤と共有バイト配列",{"categories":922,"date":923,"description":924,"image":925,"path":926,"readingTime":927,"recommend":280,"tags":931,"title":934,"type":300},[861],"2021-12-05 15:28:00","DMはファイルシステムをページとして抽象化し、ページ単位で読み書きとキャッシュを行います。データページのデフォルトサイズは8Kで、大量の書き込みではサイズの調整によって性能を高められます。実装済みの汎用キャッシュ基盤を使い、ここではページ構造を具体的に定義して、効率よくページを管理します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FjlFC4E.webp","\u002Fprojects\u002Fmydb\u002Fmydb3",{"text":883,"minutes":928,"time":929,"words":930},7.14,428400,1428,[872,740,932,933],"データページ","キャッシュ管理","MYDB 3. データページのキャッシュと管理",{"categories":936,"date":937,"description":938,"image":939,"path":940,"readingTime":941,"recommend":280,"tags":945,"title":948,"type":300},[861],"2021-12-08 22:55:00","MYDBでは、クラッシュ後にデータを復旧できるよう、ログファイルが重要な役割を担います。DMは下位のデータを操作するたびにログを生成・記録し、連続したログ列を作ります。チェックサムと各操作の記録を含む所定のバイナリー形式で保存することで、再起動時にデータの状態を正確に再構築し、整合性と完全性を保ちます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FTRcbsj.webp","\u002Fprojects\u002Fmydb\u002Fmydb4",{"text":804,"minutes":942,"time":943,"words":944},12.685,761100,2537,[872,740,946,947],"データベースログ","クラッシュリカバリ","MYDB 4. ログファイルと復旧戦略",{"categories":950,"date":951,"description":952,"image":953,"path":954,"readingTime":955,"recommend":280,"tags":959,"title":962,"type":300},[861],"2021-12-11 15:16:00","ページインデックスはDM層の重要な構成要素です。各ページの空き容量をキャッシュすることで挿入処理を効率化し、上位モジュールが長い探索をせずに適切なページを素早く見つけられるようにします。実装ではデータ項目（DataItem）の抽象化とも密接に連携し、データベースの効率的な動作を支えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002F22PSG1.webp","\u002Fprojects\u002Fmydb\u002Fmydb5",{"text":432,"minutes":956,"time":957,"words":958},9.86,591600,1972,[872,740,960,961],"ページインデックス","データ管理","MYDB 5. ページインデックスとDMの実装",{"categories":964,"date":965,"description":966,"image":967,"path":968,"readingTime":969,"recommend":280,"tags":973,"title":977,"type":300},[861],"2021-12-18 14:58:00","VMは二相ロックでスケジュールの直列化可能性を保証し、多版型同時実行制御（MVCC）を導入して読み取りと書き込みの相互ブロックを解消します。また、データベース操作の競合を定義し、特に更新と読み取りの関係を整理することで、トランザクションの分離レベルを理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002F8YzotA.webp","\u002Fprojects\u002Fmydb\u002Fmydb6",{"text":617,"minutes":970,"time":971,"words":972},14.665,879900,2933,[872,740,974,975,976],"MVCC","トランザクション分離","二相ロック","MYDB 6. レコードのバージョンとトランザクション分離",{"categories":979,"date":980,"description":981,"image":982,"path":983,"readingTime":984,"recommend":280,"tags":988,"title":991,"type":300},[861],"2021-12-23 21:20:00","VMでは、MVCCに伴うバージョンの飛び越しとデッドロックに対処する必要があります。MYDBはトランザクションに印を付けるだけで取り消しやロールバックを行い、abortedなトランザクションのデータがほかへ影響しないようにします。この設計により並行処理の効率と信頼性を高め、従来の2PLで起こりがちなデッドロックを避けて、システム全体の安定性と性能を向上させます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBF3yDW.webp","\u002Fprojects\u002Fmydb\u002Fmydb7",{"text":282,"minutes":985,"time":986,"words":987},11.32,679200,2264,[872,740,989,990],"デッドロック検出","バージョン管理","MYDB 7. デッドロック検出とVMの実装",{"categories":993,"date":994,"description":995,"image":996,"path":997,"readingTime":998,"recommend":280,"tags":1002,"title":1005,"type":300},[861],"2021-12-24 21:01:00","MYDBはB+木によるクラスタ化インデックスを実装します。IMはバージョンマネージャー（VM）を経由せず、データマネージャー（DM）と直接やり取りし、インデックスデータをデータベースファイルへ直接書き込みます。この章では二分木インデックスの構造を詳しく説明し、葉フラグ、キー数、兄弟ノードの識別子など、インデックス検索の基盤となる要素を扱います。","https:\u002F\u002Fblog-img.774352199.xyz\u002Ff92X4o.webp","\u002Fprojects\u002Fmydb\u002Fmydb8",{"text":311,"minutes":999,"time":1000,"words":1001},6.53,391800,1306,[872,740,1003,1004],"B+木","データベースインデックス","MYDB 8. インデックス管理",{"categories":1007,"date":1008,"description":1009,"image":1010,"path":1011,"readingTime":1012,"recommend":280,"tags":1016,"title":1019,"type":300},[861],"2021-12-25 15:44:00","テーブルマネージャー（TBM）は、フィールドとテーブルの構造を管理します。ParserはSQL風の文を構造化して解析し、文に含まれる情報を対応するクラスへまとめることで、その後の操作を簡単にします。この章ではMYDBのSQL構文も紹介し、管理処理全体を理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FzOMyv5.webp","\u002Fprojects\u002Fmydb\u002Fmydb9",{"text":883,"minutes":1013,"time":1014,"words":1015},7.99,479400,1598,[872,740,1017,1018],"SQL解析","テーブル管理","MYDB 9. フィールドとテーブルの管理",1789914057610]