Rust製の組み込みOS『Tock』について調べてみた
これは 自作OS Advent Calendar 2019 の9日目の記事です.
はじめに
最近大人気ですよね,Rust. 全人類Rust書いとる...俺は... システムプログラミング言語ですし,LLVMを使っているので色々なアーキテクチャ向けにコンパイルできますし, 安全性を重視しているので,RustでOSが書けるようになると色々と面白そうです.
とはいえ,なんだかんだでちゃんと使ってみようという気になれず,まだあまり書いたことがありません. そこで,今回はRustで書かれたOSであるTockを使って,モダンな言語でのOSの作り方やRustそのものについて調べてみようと思います.
Tockとは
TockはRustで書かれたCortex-MやRISC-Vで動く組み込みOSです.
最近はSTM32でも動くらしいですね.
https://garasubo.github.io/hexo/2019/02/18/tockapp.html
とりあえず動かしてみる
何はともあれ,まずは動かしてみましょう. Getting Started Guideに従います.
まずはRustの環境構築と,tockloaderのインストールです. 実はここでrustupで指定されたバージョンのRustを入れるだけのはずなのにnightlyだとclippyが云々とか言われて激しく躓いたんですが,rustupってそういうもんなんですかね...? よく分からないけど,もうちょっとどうにかならないんだろうか(割と公式っぽいところの記述通りにやってもだめだったりするの初心者殺しでは?).
次に,カーネルをコンパイルします. カーネルのコンパイルはボード毎のディレクトリで行うようです.
$ cd boards/nucleo_f446re/ $ make -n RUSTFLAGS="-C link-arg=-Tlayout.ld -C linker=rust-lld -C linker-flavor=ld.lld -C relocation-model=dynamic-no-pic -C link-arg=-zmax-page-size=512" cargo build --target=thumbv7em-none-eabi --release "/home/sksat/.rustup/toolchains/nightly-2019-10-17-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm"-size target/thumbv7em-none-eabi/release/nucleo_f446re cp target/thumbv7em-none-eabi/release/nucleo_f446re target/thumbv7em-none-eabi/release/nucleo_f446re.elf "/home/sksat/.rustup/toolchains/nightly-2019-10-17-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm"-objcopy --output-target=binary target/thumbv7em-none-eabi/release/nucleo_f446re.elf target/thumbv7em-none-eabi/release/nucleo_f446re.bin $ make Compiling tock-registers v0.3.0 (/home/sksat/github/tock/libraries/tock-register-interface) Compiling tock-cells v0.1.0 (/home/sksat/github/tock/libraries/tock-cells) Compiling enum_primitive v0.1.0 (/home/sksat/github/tock/libraries/enum_primitive) Compiling nucleo_f446re v0.1.0 (/home/sksat/github/tock/boards/nucleo_f446re) Compiling tock_rt0 v0.1.0 (/home/sksat/github/tock/libraries/tock-rt0) Compiling kernel v0.1.0 (/home/sksat/github/tock/kernel) Compiling cortexm v0.1.0 (/home/sksat/github/tock/arch/cortex-m) Compiling capsules v0.1.0 (/home/sksat/github/tock/capsules) Compiling cortexm4 v0.1.0 (/home/sksat/github/tock/arch/cortex-m4) Compiling stm32f4xx v0.1.0 (/home/sksat/github/tock/chips/stm32f4xx) Finished release [optimized + debuginfo] target(s) in 6.91s text data bss dec hex filename 55809 2180 71548 129537 1fa01 target/thumbv7em-none-eabi/release/nucleo_f446re
最近はxargo?とかいうのを使わずともcargoで行けるんですね. ようするにcargoでターゲットを指定してビルドして,生成されたELFファイルをllvm-objcopyで素のバイナリにしているだけですね. また,cargoの出力からアーキテクチャ依存部分,ボードやSoC,ランタイム,Capsule,カーネル本体がRustのライブラリとして実装されていることも分かりました.
コンパイルができたので,まずはこのカーネルを手持ちのボードに書き込んでみます. 今回はSTM32F446を使いました(買ってくれた@tnishinagaさんありがとうございます). ...と思ったのですが,何故か書き込みができなくなってしまった(昨日はできたんだけどなあ...)ので, これ以降はnRF52840-DKを使います.申し訳...
(挙動からしてケーブルの接触不良感がするんですが諸事情により今使えるUSB mini Bなケーブルが1本しかないんですよね.マイコン弄りには致命的です.)
$ make flash Finished release [optimized + debuginfo] target(s) in 0.00s text data bss dec hex filename 94208 2464 259680 356352 57000 target/thumbv7em-none-eabi/release/nrf52840dk tockloader flash --address 0x00000 --jlink --board nrf52dk target/thumbv7em-none-eabi/release/nrf52840dk.bin Flashing binar(y|ies) to board... Using known arch and jtag-device for known board nrf52dk Finished in 0.560 seconds
書き込めたようです.
カーネルが書き込めたので,次はアプリケーションを動かしてみましょう(Tockではカーネルとアプリケーションは別に突っ込むみたいです). アプリケーションの書き込みには,専用ツールのtockloaderを使います. tockloaderはPython3で書かれています. 3で良かった...こういうのがPython2なのってたまによくあるけどめっちゃイラッとするんですよね.2019年も終わりますからね. Python2は速やかに滅ぼしましょう.
まずは対応しているボードを確認します.
$ tockloader list-known-boards Known boards: hail, imix, nrf51dk, nrf52dk, launchxl-cc26x2r1, ek-tm4c1294xl
あれ?もしかして結局STM32使えなかったオチ? まあ割と最近追加されたターゲットらしいですし,そのうち実装されるでしょう.
ということで,最初はblink
というアプリケーションを書き込んでみます.
$ tockloader install --port /dev/ttyACM0 --board nrf52dk --jlink blink Could not find TAB named "blink" locally. [0] No [1] Yes Would you like to check the online TAB repository for that app?[0] 1 Installing apps on the board... Using known arch and jtag-device for known board nrf52dk Finished in 2.497 seconds
どうやら,アプリケーションはTAB
という単位で管理されており,オンラインのTABリポジトリに登録されているexampleなどはダウンロードして使えるようです.
めっちゃ光るやん pic.twitter.com/n1jlE1m3Wy
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年12月9日
めっちゃ光ります.
アプリケーションを見てみる
アプリケーションの実装例はC/C++のものとRustのものがあるようです. 正確には,これらはC/C++とRust向けのユーザランドライブラリ群で,examplesにそれを使ったサンプルがあるかんじです. newlibとかluaとか使えるみたいですね.良さそう.
Rustはまだあんまり分かっていないので,ここではlibtock-cを見てみます. まずはblinkです.
#include <led.h> #include <timer.h> int main(void) { int num_leds = led_count(); for (int count = 0; ; count++) { for (int i = 0; i < num_leds; i++) { if (count & (1 << i)) { led_on(i); } else { led_off(i); } } delay_ms(250); } }
とりあえずこれもコンパイルして書き込んでみましょう.
$ git clone https://github.com/tock/libtock-c $ cd libtock-c $ cd examples/blink $ make ~~~libtockのビルド~~~ Application size report for architecture cortex-m0: text data bss dec hex filename 1240 188 352 1780 6f4 build/cortex-m0/cortex-m0.elf Application size report for architecture cortex-m3: text data bss dec hex filename 992 188 352 1532 5fc build/cortex-m3/cortex-m3.elf Application size report for architecture cortex-m4: text data bss dec hex filename 992 188 352 1532 5fc build/cortex-m4/cortex-m4.elf $ tockloader install --port /dev/ttyACM0 --board nrf52dk --jlink build/blink.tab Installing apps on the board... Using known arch and jtag-device for known board nrf52dk Finished in 2.916 seconds
最初と同じように光ったので,delayの時間を少し変えてコンパイルし直してみます.
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年12月9日
チカチカの間隔が長くなりましたね.ちゃんとビルド・書き込みができているようです.
さて,ここで気になるのがこのアプリケーションがどのようにビルドされているのかということです. ビルド時にアーキテクチャやボードは指定していないですし,make時のログを見る限りどうもCortex-M0,3,4向けにそれぞれビルドしているみたいです. ということでbuild/とtabファイルを見てみます.
$ ls build blink.tab cortex-m0/ cortex-m3/ cortex-m4/ $ file build/blink.tab build/blink.tab: POSIX tar archive (GNU) $ tar xvf build/blink.tab metadata.toml cortex-m0.tbf cortex-m0.bin cortex-m3.tbf cortex-m3.bin cortex-m4.tbf cortex-m4.bin $ cat metadata.toml tab-version = 1 name = "blink" only-for-boards = "" build-date = 2019-12-09T10:00:29Z
あっそういうことなの... とりあえず全部ビルドしてtarに突っ込んでるんですね. TABってtar archiveだったのか... つまり,書き込み時にtockloaderがtarを展開してmetadata.tomlを見ていいかんじに察して対応するアプリケーションのバイナリイメージだけを書き込んでいるということです. まあ,カーネルとアプリケーションが分離されているし基本的なアプリケーションを作る時にはアーキテクチャ毎にビルドしちゃって良いというのは分からないでもないんですが, 必要なやつだけビルドしたいなあ感が否めないですね.
さて,次に気になるのはled.h
です.
どのようにアプリケーションからカーネルを叩いているのかです.
libtock/led.c
を見てみると,led_on()
はこんなかんじになっていました.
~~~ int led_count(void) { return command(DRIVER_NUM_LEDS, 0, 0, 0); } int led_on(int led_num) { return command(DRIVER_NUM_LEDS, 1, led_num, 0); } ~~~
どうやらcommand()
がシステムコールラッパー的なやつで,LEDに関する操作は第一引数をDRIVER_NUM_LEDS
にするとよいっぽいですね.
command()
はlibtock/tock.c
で実装されていました.
int command(uint32_t driver, uint32_t command, int data, int arg2) { register uint32_t r0 asm ("r0") = driver; register uint32_t r1 asm ("r1") = command; register uint32_t r2 asm ("r2") = data; register uint32_t r3 asm ("r3") = arg2; register int ret asm ("r0"); asm volatile ( "svc 2" : "=r" (ret) : "r" (r0), "r" (r1), "r" (r2), "r" (r3) : "memory" ); return ret; }
SVC命令で割り込みを発生させてカーネルを呼んでいるみたいですね. r0のdriverがLEDとかButtunとかの大雑把なドライバ(Capusle毎とかなのかな?)の指定に使われていて, そのドライバに対してコマンドと2つの引数を指定できるようです.
ドライバ番号は以下のようになっていました. 結構色々ありますね.
値 | |
---|---|
DRIVER_NUM_ALARM | 0x0 |
DRIVER_NUM_CONSOLE | 0x1 |
DRIVER_NUM_LEDS | 0x00000002 |
DRIVER_NUM_BUTTON | 0x3 |
DRIVER_NUM_ADC | 0x5 |
DRIVER_NUM_DAC | 0x6 |
DRIVER_NUM_ANALOG_COMPARATOR | 0x7 |
DRIVER_NUM_SPI | 0x20001 |
DRIVER_NUM_USB | 0x20005 |
DRIVER_NUM_RNG | 0x40001 |
DRIVER_NUM_CRC | 0x40002 |
DRIVER_NUM_APP_FLASH | 0x50000 |
DRIVER_NUM_NONVOLATILE_STORAGE | 0x50001 |
DRIVER_NUM_SDCARD | 0x50002 |
DRIVER_NUM_TEMPERATURE | 0x60000 |
DRIVER_NUM_HUMIDITY | 0x60001 |
DRIVER_NUM_AMBIENT_LIGHT | 0x60002 |
DRIVER_NUM_NINEDOF | 0x60004 |
DRIVER_NUM_TSL2561 | 0x70000 |
DRIVER_NUM_TMP006 | 0x70001 |
DRIVER_NUM_LPS25HB | 0x70004 |
DRIVER_NUM_LTC294X | 0x80000 |
DRIVER_NUM_MAX17205 | 0x80001 |
DRIVER_NUM_PCA9544A | 0x80002 |
DRIVER_NUM_GPIO_ASYNC | 0x80003 |
DRIVER_NUM_NRF_SERIALIZATION | 0x80004 |
DRIVER_NUM_I2CMASTERSLAVE | 0x80020006 |
次に,せっかくなのでlibtock-rsの方も見てみました. 時間がありませんでした.
ブートシーケンスとアプリケーションの実行
さて,一通り使ってみたところで,Tockがどのように起動するのか調べてみましょう. とはいっても,大体はTock Startupに書いてある通りです.
まず,Tockには.vectors
と.irqs
の2つのテーブルがあります.
Cortex-Mはベクタテーブルのリセットハンドラに関数ポインタを突っ込んでおくだけで,起動(リセット)後即その関数に飛んでくれるお手軽アーキテクチャなので,
この中にあるtock_kernel_reset_handler
が最初に呼ばれる関数というわけです.
また,Rustでは#[link_section=".vectors"]
のように書いておけば変数が置かれるセクションを指定できるようです.素晴らしい.
#[used]
で最適化で消されないようにもできるんですね.
ここで指定されているリセットハンドラはboards/<board>/src/main.rs
にあるようです.ボード毎に実装されているわけですね.
リセットハンドラは以下のような実装になっていました.
#[no_mangle] // これでマングリングしないようにできるっぽい pub unsafe fn reset_handler() { stm32f4xx::init(); // ボード毎の初期化処理 // ペリフェラルとか諸々の初期化 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES)); let chip = static_init!( stm32f4xx::chip::Stm32f4xx, stm32f4xx::chip::Stm32f4xx::new() ); // Console, LED, Buttunなどのcapsuleの生成 // ボードの構造体 let nucleo_f446re = NucleoF446RE { console: console, ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), led: led, button: button, alarm: alarm, }; debug!("Initialization complete. Entering main loop"); extern "C" { static _sapps: u8; } kernel::procs::load_processes( board_kernel, chip, &_sapps as *const u8, &mut APP_MEMORY, &mut PROCESSES, FAULT_RESPONSE, &process_management_capability, ); board_kernel.kernel_loop( &nucleo_f446re, chip, Some(&nucleo_f446re.ipc), &main_loop_capability, ); }
最初にボード毎の初期化やペリフェラルの初期化をしていますね.
その後,board_kernel
という変数を定義しています.
これがこのボードにおけるカーネルを表現するための構造体か何かっぽいです.
static_init!()
が何をするマクロなのかは分かりませんが,多分kernel::Kernel
の型の変数なのでしょう.
その後に定義しているchip
はどうやらSoCに載っている諸々が実装されたものっぽいですね.
これはボードとは別にtock/chips/
以下に実装されています.GPIOのレジスタとか,そういうやつです.
その後は,console
, led
, buttun
などの抽象化されたデバイスが定義されています.
どうやらこれらの構造体はTockではCapsule
と呼ばれているようです.
TockのArchitectureを見てみると,カーネルがCore KernelとCapsuleに別れていることが分かります. Core Kernelはできるだけ小さくして,実際のハードウェアアクセスはCapsuleでやる,というかんじなんですかね. また,CapsuleはRustの構造体として実装され,明示的に指定されたリソースにのみアクセスできるので安全!とのことです.
Capsuleを作ったら,ボードの構造体にCapsuleを突っ込んで初期化は終わりです.
初期化が終わったら,kernel::procs::load_processes
でプロセスをロードします.
_sapps
はアプリケーションのバイナリイメージを含むROMの領域のアドレスです.boards/kernel_layout.ld
で定義されています.
kernel::procs::load_processes
の実装を読んでみると,PROCESSESの数だけProcess::create()
でプロセスを生成しているようでした.
あと,多値返却とかもできるんですねRust.
ちなみに,APP_MEMORY
はstatic mut APP_MEMORY: [u8; 65536] = [0; 65536];
となっていたので,アプリケーションは最大64KiBのメモリを使うことができるようです.
これでプロセスができたので,後はboard_kernel.kernel_loop()
でメインループに入っています.
このメインループはtock/kernel/src/sched.rs
で実装されており,
プロセスはスケジューラによってスケジューリングされつつ,process::State::Running
の時に実行されるようです.
おわりに
実はこの記事は2,3日で急いで書いたので今回はここまでとします. ちなみに書いてる途中に良さげな似たような記事を見つけて焦って内容を増やしました. でも,あんまり「Rustでどういうところがうれしいのか」みたいなところまで調べられませんでした. そもそも僕自身ほとんどRust書いたことがなくてなんもわかっとらんというのもあります.
とはいえ,最近はxv6とかLinuxとかのソースコードしか読んでなかったので,「おお〜モダンな言語っぽい書き方だなあ」という気持ちになりました. ボードとかSoCとかもちゃんと分けられていますしね. インターン先でZenで書いてるOSと似たものを感じました.
でも,チラッと見た限りですがポインタ操作とかちょっとめんどくさそうだな〜という気持ちにもなりました. もちろんユーザーアプリケーションを書く時にはあんまりポインタ使うべきではない/使うとしても安全に使えるようにすべき,というのは分かるんですが, ベアメタル環境で動くプログラムだとそうもいかないですよね.ペリフェラル弄ったりとか. 個人的にはそこらへんはZenの方が楽かな,と思いました(別にステマとかじゃないですよ).
あと,色々読んでみてRust結構良い言語だな〜となるやつ(N回目)をやったので, 少しずつRustでプログラム書いていきたいですね. やっていくぞ.
夏休みにconnectFreeのインターンに行った話
3週間京都でインターンしてた
ブログ書くのめっちゃ久しぶりですね.sksatです.
ちなみに大学生になりました. 大学受験のこととか,大学生活のこととかはそのうちなんか書こうと思います.
で,まあなんだかんだあったとはいえ大学生という身分を利用して最近色々やってます. 研究室入ったり,ロケット打ったりとかね.
あと,長い夏休みを利用して3週間ほどconnectFreeという会社にインターンに行ったりしてました.今回はその話です.
経緯
一般的なインターンって,会社が募集して学生が申し込んで,なんかしらの選考を受けて...とかやるらしいんですが, 今回は全然そんなかんじじゃなくて,行きたいな〜と思っていたらスッと決まっていました.すげえ.
多分最初にconnectFreeに興味を持ったのはLDScellさんのブログ記事だったと思います.
「アホだから,やるんだよ!」,なんでもかんでも自分で車輪の再発明しちゃいたいオタクっぽくてめちゃめちゃ好き. 低レイヤで面白いことやってる企業ってだけでもう興味しかないですね. その後,鮟鱇さんのツイートを見て更に興味が湧きました.
以前WANTEDされたconnectFreeさんに @PiBVT と遊びに行ってきました。諸々変態的なプロジェクトを見せてもらいました。低レイヤーができる学生を探しているそうなので興味がある方は是非。
— 艮 鮟鱇/うしとら あんこう (@ushitora_anqou) 2019年6月12日
僕は計算機弄りが大好きで,大学も計算機弄るために進学したようなものです. なので,バイトとかやるとしても計算機弄りがいいなあと思っていました(まあ,他が無理というのもあります). でも,計算機弄ってたらお金が貰えるようなものって大体Web〜,とかスマホアプリ〜,とかばっかりじゃないですか(偏見). そもそも僕が計算機弄りを初めたきっかけは中学生の時に『30日でできる!OS自作入門』に何故か出会ってしまったからで, それからも低めのレイヤでわちゃわちゃするか数値計算っぽいことをやるかぐらいしかしてませんでした. ゲーム自作とかもほとんどやったことないですし.
もちろん,組み込み系のところを探せば低レイヤでわちゃわちゃすることもできると思うんですが, あんまりこのご時世に責任が発生するものをCでゴリゴリと書きたくはないですね... 贅沢かもしれないですがせめてC++(11,14,17)は使いたいですし,ナウでホットなRustとか使ってたらめっちゃ良いですよね. Rustあんまり書いたことないけど.
そんなことを思いながらなんとなくバイトを探すなどしていたんですが, そこでこんなものを見たらエーッッッこれ面白そう!!!ってなっちゃうわけです.
そんなこんなでconnectFree面白そうだな〜と思ってツイッターをしていたらなんか見学させてもらえることになったので見学させてもらいました.
見学では,
- EVER/IPのデモ
- Zen言語
- NETBOY
などを軽く見せてもらいました.
EVER/IPはL3のセキュアなプロトコルで, アドレスなどがIPv6互換になっているため,上のレイヤのソフトウェアを書き換えることなく導入が可能になっています. 実際に,connectFreeのGitLabはEVER/IPを使って運用されていて,「自社プロダクトで開発環境が運用されてるのめちゃめちゃ良いな...」と思いました.
ZenはconnectFreeが独自開発しているシステムプログラミング言語で,Zigという言語をforkしたものです. ベアメタル環境などで使われることをとても意識した言語で,標準ライブラリも多くのものがベアメタル環境でも使うことができるようになっています. その上,パターンマッチなどのモダンな言語機能や,メモリアクセスの範囲チェックをコンパイル時に行ってくれたりします.
NETBOYは独自のボードで,もちろんこれの上で動くOSもZenで書くとの話でした.
connectFree、プログラミング言語も作ってるし他にも色々やっているし何でもフルスクラッチしたいオタクにはめちゃめちゃに良さそうという気持ちになった
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年6月21日
気持ちになりました.はい.
めちゃめちゃ良さそうだったので,帰り際にぜひバイトとかしてみたいですね〜みたいなことを話しました.
その後,第15回Kernel/VM探検隊に行ったらconnectFreeのCEOが発表してたので, 直接会って話したら,「来たらええやん!」と言われてなんか京都に行くことになっていました.ウケる.
経緯としてはこんなかんじです. そんなわけで9/2〜9/20の間京都に行ってじっくりインターンをやらせてもらいました. ちなみに,京都までの交通費はもちろん,インターンの間住む所の手配とかも全部総務の人がやってくれました.
やったこと
Zen言語の学習
connectFreeでは色々なソフトウェアがZenで書かれているため, 最初の数日はZen言語の学習をしていました. @LDScellさんが作っていた色々なドキュメント(zenbeddedとか)を見ながら色々書いてはコンパイラに怒らていました. ちゃんと怒ってくれるコンパイラも,ベアメタルでも使える色々な標準ライブラリも,諸々のモダンな文法もすげえ...ってなってました.
現在は基本文法・標準ライブラリのドキュメントが公開されているので,興味がある人は見てみてください. Public Beta版のコンパイラも公開されているので,ぜひ遊んでみてください!
個人的には,u1,u2みたいなビット数を指定した変数を作ることができるとことか, comptimeでコンパイル時計算がゴリゴリできるところとか, interfaceとか,UEFIプロトコルが標準ライブラリにあるところとかが好きです.
Zenを使った(組み込み)OS開発
Zenを一通り学んだ後,Zenで組み込みOSを作っていました.やったぜ. 独自のプログラミング言語で独自のOSをフルスクラッチできるインターンとか最高すぎるし他では(多分)絶対できないんだよなあ...ありがてえ...
どのZenの機能をどう使ったら綺麗に実装できるかな〜と考えてコンパイラに怒られるのは楽しかったです. また,途中からこのOSは複数人で開発することになったのですが,今まで複数人での開発というものをやったことが無かったので色々と新鮮でした.
あと,インターン中にもZenコンパイラはゴリゴリと実装が進められていくので, それを眺めるのも,出社即git pullしてmakeするのも,「エーッ先週CEOと話してたことが新機能として生え初めてる!?」ってなるのも楽しかったです.
その後
これは貰ったおもちゃ(開発ボード) pic.twitter.com/brz9RRmOeJ
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年9月20日
インターン中に弄っていた開発ボードを貰うなど.中々高機能なので弄り甲斐があるボードです.
そして,お賃金の方も結構いただけたので,思い切って人生初の「自作PC」ってやつをやりました. まあ自作といっても本当に買ってきたパーツを組み上げるだけでしたが.
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年10月5日
あとなんかアキバでオタクに煽られて光るメモリにしました. メモリが光ると何がうれしいのかよく分かりませんが,なんとメモリが光るんですよね.
ツクモでクリアファイル買ったら光るメモリが付いてきたんですよね pic.twitter.com/nrmVTtzQWv
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年10月5日
あと調子に乗ってNVMeにしました.速くてうれしい.
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年10月11日
もちろんArch Linuxを入れました.
— お前はやがて君になったか?俺は死んだ (@sksat_tty) 2019年10月9日
また,インターンが終わった後もリモートでちょいちょい働かせてもらえることになりました. というかしてます.やったね! 多分また長期休暇期間に京都行って集中的にやりたいなーとも思ってます.
あと,僕はどうやらconnectFree初のインターン生だったみたいなのですが, 技術書執筆サークルの強いオタクがconnectFreeに興味を持っていたので社の人に紹介したらちょうど僕と入れ替わりぐらいのタイミングで京都に吸い込まれていきました.
89/100
— Drumato (@drumato) 2019年11月7日
・インターン
・こんなに楽しいとは思わなかった
・無限にZen書いてる
明日
・インターン#100dPeach
元気にZenを書いているみたいで何よりです. 僕も元気にZenを書いていきたいですね. そのうちロケットの電装に使いたいなあ...
技術書典4に行ってきた
行ってきた. あ,ちなみにこれからはなんかイベントとか行ったら雑でもなんか書くことにしました. あとはパソコンカタカタのシンチョクをにょろ〜んと書いていければ最高ですね.
技術書典,何
一言で言うと技術書版のコミケ.たぶんそれで大体あってる. 技術書,と言っても大半は個人/団体の同人誌ですが.
詳しくは公式サイトを見てくだしあ.まあ正直ここだけ見てもなんもわからんが.
前日
みんな技術書典、何時に行くの?
— おもち (@mochimochi0x) 2018年4月21日
起きたとき
— 千種夜羽△ (@sksat_tty) 2018年4月21日
9時に秋葉原に集合するらしい。
— 双葉 杏 (@megumish) 2018年4月21日
9時に集合=それより前に起きる=無理では? となった無理では
— 千種夜羽△ (@sksat_tty) 2018年4月21日
あーメモリがオワオワリした
— 千種夜羽△ (@sksat_tty) 2018年4月21日
@フォロワー
— 千種夜羽△ (@sksat_tty) 2018年4月21日
あしたは技術書典なのでがんばってぼくを起こしてくだしあ
— ⚡すく⚡ (@0214sh7) 2018年4月21日エラいので寝た.
朝
天才なので8時台に起きた.ピッ
— 千種夜羽△ (@sksat_tty) 2018年4月21日
出発したのが9時半.何故? その衝撃的な理由は↓アキバ行くぜ!(ガタッ
— 千種夜羽△ (@sksat_tty) 2018年4月22日
10:40とか四捨五入したら10時じゃん
— 千種夜羽△ (@sksat_tty) 2018年4月22日
「元々何時集合だったんだっけ?」
— 千種夜羽△ (@sksat_tty) 2018年4月22日
「9時だね」
「起きられそうにないから何時にしてもらったんだっけ?」
「…10時だね」
「もひとつ聞こうか、今は何時?」 pic.twitter.com/WKiwybwhx0
しかし技術書典は待ってくれない.
#技術書典 整理券配布開始しました!
— 技術書典公式アカウント (@techbookfest) 2018年4月22日
まってまって
— 千種夜羽△ (@sksat_tty) 2018年4月22日
て,ておくれてないし...なんでみんなておくれずにこんな朝早くから活動できてるの?家が近いの?オタクじゃないの?
— 千種夜羽△ (@sksat_tty) 2018年4月22日
なんか釣り堀っぽいやつ見かけた.たのしそう.なんかたのしそう pic.twitter.com/pqWEEREshb
— 千種夜羽△ (@sksat_tty) 2018年4月22日
着いた.整理券配布最後尾
— 千種夜羽△ (@sksat_tty) 2018年4月22日
人間が多すぎて整理券もらうのにすごく並んだ.@整理券もらったオタク
— 千種夜羽△ (@sksat_tty) 2018年4月22日
整理されるぞ
オタクが囚人番号ツイートしてるのなに?
— みすど(22歳 男性 千代田区美人OL) (@MysticDoll) 2018年4月22日
収容番号408です。
— 双葉 杏 (@megumish) 2018年4月22日
技術書典では一意な囚人番号が割り当てられます.907番です
— 千種夜羽△ (@sksat_tty) 2018年4月22日
囚人の入荷はやくない?
— 千種夜羽△ (@sksat_tty) 2018年4月22日
囚人が大量輸送されてた(整理券配布列).手上げて輸送されるオタク、完全に囚人
— 千種夜羽△ (@sksat_tty) 2018年4月22日
「奴」がいた(もちろん買った).友利奈緒おるやん pic.twitter.com/RzfrFEbN2R
— 千種夜羽△ (@sksat_tty) 2018年4月22日
人間がいすぎて全くツイートができなかった. 気がついたら金を失い謎の紙束を所持していた.何も分からない、気が付いたら金が消え謎の紙を持っていた#技術書典4 pic.twitter.com/4aoX7xiqcW
— 千種夜羽△ (@sksat_tty) 2018年4月22日
どうもsatさんが学ランネタを気に入ったらしい.satさんに「今日は学ランじゃないんですねw」って言われたのクソ面白かった
— 千種夜羽△ (@sksat_tty) 2018年4月22日
昼
satさんのMeltdown本が欲しかったが,まだ紙になったものが届いていなくて,それが1時くらいにくるらしいとのことだったのでとりあえずオタクで集まって飯を喰った.よくわからないが飯を食って戻るとMeltdownできそう
— 千種夜羽△ (@sksat_tty) 2018年4月22日
— 千種夜羽△ (@sksat_tty) 2018年4月22日「ラ!」と叫ぶと替え玉が無料で降ってくるのでつい喰いまくってしまった.2回替え玉した.
午後
Meltdown本の印刷物を持った人が間もなく現地に到着予定。その後諸手続きの後、売り出し開始です。電子も
— sat (@satoru_takeuchi) 2018年4月22日
舞い戻ってきた#技術書典4
— 千種夜羽△ (@sksat_tty) 2018年4月22日
windholeブース(け51)の新刊「図解でわかるMeltdown」の紙版&電子版、および「Btrfsの薄い本」の紙版、販売開始です。これらを狙って朝来てくださった方、すいませんでした。ついにきました!#技術書典 #技術書典4
— sat (@satoru_takeuchi) 2018年4月22日
というわけで戻ってきてMeltdownした. この時点でもまだ整理券配布の列はかなり長くて,入場できるのが2700番までとかだった.Meltdown入手!#技術書典4
— 千種夜羽△ (@sksat_tty) 2018年4月22日
すぐこういうことする. こういうことしてるから後ろから近づいてきたオタクにこっそりカバンにメモリ入れられそうになるんですよ.ミステリーサークル情報です pic.twitter.com/jK2OiulF9z
— おつよん🦖 (@Otyn0308) 2018年4月22日
オタク闇取引#技術書典4 pic.twitter.com/1InKgKOBoV
— 千種夜羽△ (@sksat_tty) 2018年4月22日
というのはネタで,ThinkPadでRAM4GBでがんばっていたらすぐメモリがオワオワリするのでTLに念を送ったらフォロワーからメモリが生えてきたのでした.感謝!!!!! ちなみに今まで4GB以上の環境を使ったことがない.本当は鞄のなかにさりげなくいれるつもりでした。() https://t.co/QJhL4sIlBr
— yujaku (@yujaku_aa) 2018年4月22日
計画性が皆無なのでZIPを完全理解しそこねた.「ZIP、完全に理解した」は完売しました。「ksnctf C92」はもう少し在庫があります。「モナーでもわかるビットコイントランザクションスクリプト(プレビュー版)」はまだまだあります。 #技術書典https://t.co/BB3lOsWsrO
— superflip (@sprflp) 2018年4月22日
Meltdownは...ありまーす!!「Meltdownどうですかー!」「Meltdownありまーす!」
— sat (@satoru_takeuchi) 2018年4月22日
という呼び込みをしている
ここらへんで,やることが大体終わったので適当に存在しているオタクとオタクをしていたんですが解散の流れになり,megumishさんがTothenewfutureさんとエンカしそうな雰囲気を醸し出していたので適当に尾行したら結局UDXに戻ってきた&オタク音信不通になったのでmegumishさんと適当にダベってた.
ダベっていたらエモになった.カフェに来たと思ったら、エモ空間に突入した。
— 双葉 杏 (@megumish) 2018年4月22日
計画性が本当に皆無なので道端にいたフクロウカフェの宣伝の人とフクロウにつられて気がついたらフクロウカフェにいた. カフェというよりエモ空間だったが...かわいい pic.twitter.com/BiWIwpL0EG
— 千種夜羽△ (@sksat_tty) 2018年4月22日
エモ空間
メンフクロウ好きな話しましたっけ?今してますね pic.twitter.com/wO4sywxFfj
— 千種夜羽△ (@sksat_tty) 2018年4月22日
性別わかんないんですがこれは百合です pic.twitter.com/9Kfmi0chxl
— 千種夜羽△ (@sksat_tty) 2018年4月22日
フクロウカフェ,鶏が一番自由を謳歌していましたね.
🐔脱走した pic.twitter.com/ib6kM95jIC
— 千種夜羽△ (@sksat_tty) 2018年4月22日
— 千種夜羽△ (@sksat_tty) 2018年4月22日
みられてるwatching you pic.twitter.com/vTxOjcAlQo
— 千種夜羽△ (@sksat_tty) 2018年4月22日
これすき百合やんけ pic.twitter.com/JNplLBG7eZ
— 千種夜羽△ (@sksat_tty) 2018年4月22日
あと,技術書典は気がついたらすごいことになってた
技術書典、今回参加者六千人弱。前の三倍くらい??
— sat (@satoru_takeuchi) 2018年4月22日
Tothenewfutureさんとも会えたので戦果を報告しました.成果報告してる pic.twitter.com/N0ZvhyuXpx
— 千種夜羽△ (@sksat_tty) 2018年4月22日
買ったもの
買いすぎでは...戦果#技術書典4 pic.twitter.com/OT23uNUoA8
— 千種夜羽△ (@sksat_tty) 2018年4月22日
本当に面白そうなものが色々あったので気がついたら買ってましたね. レイヤーが低めのものが割とあったのも良かったです.
次は売る側で参加してみたいなあ(などと).
カーネル/VMキャンプ #7 に行ってきた
行ってきました.
最近ブログ書いてなかったのでちょっと書く.<- 書いたらTogetterか?みたいなかんじになった
なんやねんそれ
これですね. ハッカソンみたいなやつ(?)です.
まあ多分だいたい「山でオタクで集まってパソコンカタカタすると→タノシイ!」という感情が具現化したみたいなかんじ. ゆるキャン△はいいぞ.
今まで何度か探検隊とかキャンプの様子をTwitterやらYouTubeのLive中継とかで見てたんですが,「これ絶対タノシイな...」と思ったので衝動的に参加してみました. レイヤーが低めな人の界隈なのも良さがある.
1日目
1日目といいつつ,僕は土曜日も登校なので学校帰りにそのまま現地に向かいました.
おひるごはんたべてないのでおなかすいてる
— 千種夜羽△ (@sksat_tty) 2018年4月14日
おなかすいてた.新規欠食児童配送中です
— 千種夜羽△ (@sksat_tty) 2018年4月14日
はいプロ pic.twitter.com/yL51TI0EAg
— 千種夜羽△ (@sksat_tty) 2018年4月14日
立川のかにチャーハンの店おいしいよね.チャーハンははふはふしながら食べられたんだけど、味噌汁で火傷しそうになった
— 千種夜羽△ (@sksat_tty) 2018年4月14日
何度か青梅特快乗ってるのにホーム間違えて危なかった.乗り換えギリギリギリギリギリギリギリギリせーーーーフ!!!!
— 千種夜羽△ (@sksat_tty) 2018年4月14日
青 梅 線
— 千種夜羽△ (@sksat_tty) 2018年4月14日
実 家 の よ う な
安 心 感
ここらへんに来たのは久しぶりでした.登山部も引退?したし.はいどうも~ pic.twitter.com/3kgAToYL9A
— 千種夜羽△ (@sksat_tty) 2018年4月14日
この後はバスでロッジの最寄り(2km)のバス停まで行きました. 普段は最後の方までガッと乗っていく藤倉行きを途中で降りるの新鮮だった.
2kmだし歩くか〜wって思ってたら車で迎えに来てもらえました.感謝
大人二人に車で誘拐されています(迎えにきてもらった)
— 千種夜羽△ (@sksat_tty) 2018年4月14日
そんなかんじでロッジに着きました.
屋根があるのすごくない?2階まであったし(今まで山奥に来たら大抵△だったので感動した). 大型キャビン | ロッヂ神戸岩 東京都檜原村にあるキャンプ場 パワースポット神戸岩に一番近い 秋川渓谷 BBQ コテージ バンガロー テントサイト 日帰り デイキャンプ 水洗トイレ完備すごい!!!こんな山奥で屋根があるとこ入ったの初めてやんけ
— 千種夜羽△ (@sksat_tty) 2018年4月14日
着いた時は♨に行っている人などがいたので少し人数は少なかったのですが, パソコンカタカタしてるオタクや転がって寝をしているオタクなどが散乱していて「ここには...『自由』があるんか...!?」とか思いました.
あとあの小屋,トラフィック最上川は無いのは当然としても電力最上川あるのは最高でしたね. まあ無いとオタクが生きていけませんが.タコ足配線の「強さ」を感じましたね.
あとなんかかなり強いアニメ上映環境が用意されてて,割と早い段階でアニメが流れ初めてた.
焼き
— 千種夜羽△ (@sksat_tty) 2018年4月14日
オタクなので△グッズを持っていったら好評だったので良かった
— 千種夜羽△ (@sksat_tty) 2018年4月14日
未だに制服着てたことを思い出した#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月14日
制服で焼きをしていたっぽい
— 千種夜羽△ (@sksat_tty) 2018年4月14日
アニメ
今回のアニメ再生環境 #kernelvm_camp pic.twitter.com/lHdcg5MWFC
— ゆるsyuu1228△ (@syuu1228) 2018年4月14日
放課後のプレアデス
魔法のステッキが「キキーッ」とか「ブロロロ...」とか鳴るの本当にエモい.「放課後のプレアデス」が上映されているんだが、どうしても魔法のステッキの走行音で笑う #kernelvm_camp pic.twitter.com/MS8pfONNGV
— ゆるsyuu1228△ (@syuu1228) 2018年4月14日
放課後のプレアデス,ナチュラルに音速の壁越えてるなあって思ったら光速越えようとしてるな?
— 千種夜羽△ (@sksat_tty) 2018年4月14日
天文オタク的にもエモが詰まってたんですが,おるみんさんが「ここNAOJ監修」とか言っててウオオというかんじでしたね. 土星の輪のとことか4D2Uみあった.重力縮退とか言い始めたし恒星作り始めたんだがw https://t.co/durfCnihZr
— 千種夜羽△ (@sksat_tty) 2018年4月14日
プリンセス・プリンシパル
プリンセスプリンシパルが上映され初めた#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月14日
百合最高ですね.プリプリ見ながらパソコンカタカタできる環境が手に入った
— 千種夜羽△ (@sksat_tty) 2018年4月14日
クオリディアコード
クオリディアコードの円盤を買ったもののBD再生環境が無く中身を見ていなかったので見ました. 千種夜羽が出てくる11・12話しか買っていないので当然11話から流すことになり,視聴済のおるみんさん以外「?」となっていたのがチョットアレでしたね.金があれば...(とはいえ金があったら揃えるかというとウーンというかんじになる). いやでも千種夜羽最高なんですよ..@sksat_tty がクオリディアコードBD流してる #kernelvm_camp
— ゆるsyuu1228△ (@syuu1228) 2018年4月14日
クオリディアコードを唐突に11話から再生し始めたぼく「なんかところどころ動いていなかったところがが動いているが???w」
— 千種夜羽△ (@sksat_tty) 2018年4月14日
じとめしそうなキャラに関して言及があった
— 千種夜羽△ (@sksat_tty) 2018年4月14日
これ放映版と全部diffを列挙したいが?w
— 千種夜羽△ (@sksat_tty) 2018年4月14日
クオリディアコード,全く知らないフレームがあるのも知ってるけど動いてるフレームがあるのもそれらがちょこちょこあるのもおもしろいな
— 千種夜羽△ (@sksat_tty) 2018年4月14日
「修正」,っょぃ.
あと,隣で人狼やってる中,オーディオコメンタリーを聞くためだけに2.5周したのは我ながら限界だったっぽい
2日目
何も考えいないので、起きたら制服を着ていた。登校に便利そう
— 千種夜羽△ (@sksat_tty) 2018年4月15日
なんかクオリディアコード終わってしばらくパソコンカタカタしてたら外が明るくなってきてて,ついでにねむかったので何も考えずにオフトンインしてた動作ではなく、結果 https://t.co/KNrnu5jTjj
— 千種夜羽△ (@sksat_tty) 2018年4月15日
起きたらこんなかんじで最高だった.最高ですね~(その代わり花粉が強い pic.twitter.com/SKHuuimhsh
— 千種夜羽△ (@sksat_tty) 2018年4月15日
この日は適当にごはん食べに行って,
ついでに滝を見に行きました.ごはん! pic.twitter.com/iFIsLa0Xxh
— 千種夜羽△ (@sksat_tty) 2018年4月15日
よかった#kernelvm_camp pic.twitter.com/99m5pZM2h2
— 千種夜羽△ (@sksat_tty) 2018年4月15日
で,おうちにかえってきました.
おうちに帰ってきた#kernelvm_camp pic.twitter.com/EEh1nr7JqR
— 千種夜羽△ (@sksat_tty) 2018年4月15日
プリプリ再上映中(1話から)#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月15日
何故か再上映されるプリプリ.百合は脳に良いんですよ.プリプリBD一巻二周目見終わったみなさん「尊い…」「知能上がった!」#kernelvm_camp
— ゆるsyuu1228△ (@syuu1228) 2018年4月15日
アンジェさん,「歯止めが効かなくなる」じゃあないんですよ.最高か?いいぞもっとやれ.
色々な妖怪
妖怪は...います!妖怪,飯さらい・ポテチちらし,アニメ流し,現金濡らし #kernelvm_camp
— おるみん (@kotatsu_mi) 2018年4月15日
「「じとめしたら起こして」」
— 千種夜羽△ (@sksat_tty) 2018年4月14日
別フロアからちせが出てきたとたんに「ちせーっ」という声が...#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月15日
妖怪めしさらい
エビデンス僕は普通のモブキャラでしたよ。時々「ハラヘッタ」って鳴いたりしてただけで。 https://t.co/Bx2Cwft4I0
— Liva (@liva_jy) 2018年4月15日
焼きそばを作るそばから味見と言いながらヒョイパクするliva氏#kernelvm_camp #思い出すシリーズ
— 千種夜羽△ (@sksat_tty) 2018年4月15日
現代社会
#kernelvm_camp pic.twitter.com/5c5A7FeNM2
— おるみん (@kotatsu_mi) 2018年4月15日
シンチョク
sprintf関数内で無限ループになってSEGVして落ちる,みたいなバグがあって,今回のキャンプではsprintfのアセンブリ読んでこれを解決するぞ!って思ってました. で,golibcの実装読んでsprintf内のラベルのアドレス調べてそこが実行されたらダンプする,とかやってたんですがどうもアドレスが違いそうな雰囲気. で,https://github.com/HariboteOS/tolset の中にいたgolibc.libを自分でビルドしたgolibc.libに置き換えて実行してみたら完全に動作してしまった,という. まあ動いたのは良かったんですが,元々のgolibc.libでビルドしたはりぼてOSはQEMUでは動いてくれるので,バグがあるのは事実っぽいので今度原因を探りたいですね. ただ,元々のgolibc.libはfileコマンド打ってもdataって表示されるのは一体...(tek圧縮でもされてるのだろうか?golibc.libを自分でビルドし直して差し替えてコンパイルしたら普通にエミュでいけて無限に:thinking_face:になてる pic.twitter.com/B6vfUFacSH
— 千種夜羽△ (@sksat_tty) 2018年4月14日
僕はオタクの皆さんを見てオタクーッと思ったりアニメを見てケラケラ笑ったり火をヒャッハーしたりクオリディアコードを流したり微妙なプログラム書いたり学ランで行動して集団の見た目を怪しくするなどしました#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月15日
花粉が無料で手に入る檜原村
花粉が無料で手に入る檜原村#kernelvm_camp
— 千種夜羽△ (@sksat_tty) 2018年4月15日
檜原村に鼻の秘孔を突かれた
— 千種夜羽△ (@sksat_tty) 2018年4月15日
檜原村に鼻の秘孔を突かれたので朝から鼻水が止まらない
— 千種夜羽△ (@sksat_tty) 2018年4月16日
謎の要望
sksat氏は卒業してからも学ランキャラを貫いてほしい
— sat (@satoru_takeuchi) 2018年4月15日
感想
#kernelvm_camp 本当に良くて、色々なオタクがオタクだった
— 千種夜羽△ (@sksat_tty) 2018年4月15日
クソ楽しかったです.
ムラに帰りたい...
檜原村村民なので天気情報が送られてきた pic.twitter.com/wkGitmObS7
— 千種夜羽△ (@sksat_tty) 2018年4月17日
https://t.co/81xqBPF25Y
— 千種夜羽△ (@sksat_tty) 2018年4月16日
岩最高だったっぽいな...行けばよかったかも
これは事実や、結構アニメで盛り上がってる時とかが一番みんな進捗が出ていて… #kernelvm_camp
— ゆるsyuu1228△ (@syuu1228) 2018年4月15日
NimでOS開発したいねという話
これは自作OS Advent Calendar 2017 の10日目の記事です.遅刻です.
. @sksat_tty さんの担当の記事がいつ上がるかドキドキしながら待ってます
— ファッション自作OSマン (@uchan_nos) 2017年12月11日
アアアアアすみません!!!!!
では謝罪も終わったところで(こいつ反省してんのか?),Nimで自作OSしたいねーっていう話をしていきたいと思います.
そもそもNimってなによ?
プログラミング言語のひとつで,最近僕が気に入ってるやつです.
構文とかはかなりPythonっぽくて,インデントでブロックができます. フィボナッチ数列とかはこんなかんじ
proc fib(n: int): int = if n < 2: return n else: return fib(n-1) + fib(n-2) echo(fib(30))
見た目はPythonっぽいですがint
とか出てきてますね.そう,Nimは静的型付け言語なんです.
なんでNim?
さて,ここまで来て「え?そんなPythonみたいなやつどうやってベアメタルで動かすの?mrubyみたいなのあるの?*1」と思われた方もいるかもしれませんが違います.
なんでかというと,そもそもNimはコンパイル言語だからなんですね. コンパイル言語なので,コンパイルするとバイナリが出てきます(それはそう).
しかし,Nimのコンパイル手順はちょっと特殊です.コンパイルしても直接オブジェクトファイルとかは出てきません. じゃあなにが出てくるのかというと,なんとビックリ,C言語のコードが出てきます.面白くないですか?
そのため,Nimをコンパイルしてバイナリを出力する手順は,
というかんじになっています. コンパイラというよりトランスパイラに近いのかも.
Cだけではなく,C++/Objective-C/JavaScriptなどにも変換出来るらしいですね.すごい.
では,実際どんなかんじなのか,まずはちょっと普通に使ってみましょう.
ここの記事そのまんまなのでインストールは割愛します.
では,初めににハローワールドしてみます.
echo "Hello, World!"
これをhello.nim
というファイルに保存します.
で,コンパイル言語なのでコンパイルして実行形式のバイナリを作ることができます.
$ nim compile hello Hint: used config file '/etc/nim.cfg' [Conf] Hint: system [Processing] Hint: hello [Processing] CC: hello CC: stdlib_system Hint: [Link] Hint: operation successful (10984 lines compiled; 1.404 sec total; 17.938MiB peakmem; Debug Build) [SuccessX]
compile
オプションはc
としてもOK.((ここをcpp
とするとC++に,js
とするとJavaScriptに変換出来ます))
これで,hello
という実行形式バイナリが出来ました.
$ file hello hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=184748d3c78ff375408fdf598d6217f3256f5721, not stripped $ ./hello Hello, World!
しかし,先程書いたように,Nimは直接バイナリなりアセンブリなりは吐かず,代わりにCコードを生成します.
そのCコードはどこに行ったのかというと,nimcache
というディレクトリの下に生成されています.
$ ls ./nimcache hello.c hello.json hello.o stdlib_system.c stdlib_system.o
hello.c
,stdlib_system.c
というCコードが生成されていて,それをCコンパイラでコンパイルしたhello.o
,stdlib_system.o
というオブジェクトファイルが出来ているのがわかります*2.
stdlib_system.c
は共通のAPIラッパーみたいなやつなので,生成されたプログラムの本体はhello.c
です.
hello.c
を見てみると,ちょっとゴチャゴチャしています*3.
int main(int argc, char** args, char** env) { cmdLine = args; cmdCount = argc; gEnv = env; NimMain(); return nim_program_result; }
main関数はこんな感じです.
コマンドライン引数とかをグローバル変数にとっておいて,NimMain
という関数を呼び出しているだけですね.
...と思ったら,んんん!?main関数に3つ目の引数がある!?
調べてみたら,ここから環境変数が得られるらしいですね.初めて知った...
じゃあNimMain
はどうなってるのかというと,PreMain
やらinitStackBottomWith
とかいう関数を呼んだ後,NimMainInner
という関数が呼ばれ,そこからNimMainModule
を呼んでいます.
STRING_LITERAL(TM_xLHv575t3PG1lB5wK05Xqg_2, "Hello, World!", 13); 〜〜〜 NIM_EXTERNC N_NOINLINE(void, NimMainModule)(void) { nimfr_("hello", "hello.nim"); nimln_(1, "hello.nim"); printf("%s\012", ((NimStringDesc*) &TM_xLHv575t3PG1lB5wK05Xqg_2)? (((NimStringDesc*) &TM_xLHv575t3PG1lB5wK05Xqg_2))->data:"nil") ; fflush(stdout); popFrame(); }
ゴチャゴチャはしていますが,printf
で"Hello, World!"
を表示しているのが分かります.
この関数が変換されたNimコードの本体のようです.
なので,生成されたCコードを確認したくなったらここらへんを見ましょう.
というわけでやってみる
さて,これでNimがちゃんとCに変換されてprintfで文字列表示をしているのが分かりましたが,本題はここからです. 本題は何だったかというと,NimでOSを作りたいんです. 要するにNimをライブラリとかが全然ない環境でも動かしたいんです.
じゃあどうすればいいか?ここまでくれば簡単ですね. Nimコンパイラが生成したCコードで呼び出している基本的な関数を専用のやつに置き換えてしまえばいいんです!
とはいっても,printf
やらputs
をいちいち作るのは面倒なので,もうちょっと楽な手段を使います.
実はNimは,デフォルトでCに変換するだけあって,Cとの連携がしやすくなっています.具体的に言うと,インラインアセンブラみたいにCが直接書けたり(emit),Cの関数をNimの関数として呼び出すことが出来ます.
詳しくは公式のドキュメントを見ましょう.
で,こんな感じにやればベアメタルでNimが使えるのでは?と思って試行錯誤してなんとか標準Cライブラリ無しでフィボナッチを計算して出力してみたというのが,以下のリポジトリです.
しかし,このrepoをよく見てもらえると分かると思うんですが,なんか結構色々やってますね. Cのコードが66%もあります.
何故こんなことになったのかというと,あのstdlib_system.c
がかなり曲者でした.
最初はstdlib_system.c
を自作して置き換えてやればいいかなあとか思っていたんですが,バージョンによって少しづつ変わるみたいなのと,GCの処理などがあったので弄るのをやめました.
では具体的には何をやったのかというと,stdlib_system.c
でincludeしているstdio.h
とかのヘッダを自作して,そのうちの必要な関数をちまちまと実装しました.
そして,標準Cライブラリを使っていないので,アセンブラでwriteシステムコールのラッパーも書きました.*4
まあ手抜き実装なので,エラーが発生したときに呼ばれるsignal
とかはマクロで虚無に書き換えています.
でも,これはあまりにも面倒ではないですか? まあもちろん,mrubyをハイパーバイザに移植とかよりは断然楽なんですが,ここからこれを使ってOSを書いていくとなると,環境構築のコストが高いです. そして,僕が作ったものも手抜き実装なので色々と抜けているところがあります.これならC++やRustでいいじゃん...ってなっちゃいますよね.
Rustとか特に
とか出てますし.*5
「は?ベアメタルでNimやるのダルすぎ.C++/Rust使うわ」
と思うじゃん???
いやね,僕もそう思ったんですよ. でもね,違ったんですよ. あっ待ってそこの人!まだチャンネル変えないで!ここからすごいの!!! 衝撃の真実はCMの後で!
CM
えーっと,x86エミュレータを作ってm...作ってるはずです. いや進捗出てなくて申し訳ない,というか学校関連特に夏休みあたりがアすぎたはい僕もやりたいんですよでも時間がえ?時間は無かったら作るもの?それはそうはい作ります!作るぞ!!!(宣言)
衝撃の真実的なsomething(575)
はい,CM終わり(CMか?)
CMが終わったので予告していた衝撃の真実です!!!
結論から言いましょう!!!
先程僕がやったことはすべて無意味です!!!
いやあ,やってて気付いたこととかもあるので個人的には無意味ではなかったので良かったんですが,超絶楽な他の方法がありました.
気がついたきっかけはNimのコンパイルオプションを調べていた時のことです. 適当にスクロールしていたら,"embedded"という文字列を見かけた気がして,見たら,あったんです.
Nim for embedded systems
...え?embedded?組み込み?組み込み向けに使えるの????
The standard library can be avoided to a point where C code generation for 16bit micro controllers is feasible. Use the standalone target (--os:standalone) for a bare bones standard library that lacks any OS features.
え?--os:standalone
?なんですかそのいかにもって感じのオプションは!?
色々調べてみたら,CPUとかGCの設定も出来ることが分かりました. また,
using Nim / Nimrod for micro-controllers (embedded) - Nim Forum
を見てみると,
Check out nimkernel for an example of using Nim to program bare metal.
ん?????
え??????
というわけで,僕がやろうとしていたことは既にやられていたのでした.
そして,このrepoでは僕が先程やっていたようなことはやっていません!
やってみた2
さて,超簡単な解決策が見つかったので,今度こそNimでOS(っぽいもの)を作っていきましょう!
基本的には(nimkernel)GitHub - dom96/nimkernel: A small kernel written in Nimと似たようなかんじでやっていきます.
まずは,main.nim
を作ります.
proc main() {.exportc.} = return
これがmain関数になります..exportc.
というのはこの関数をCの関数にする指定です.
このmain関数はブートローダーから呼ばれるので,この指定を付けておきます.
で,あとはさっきの--os:standalone
とかのオプションをつけてコンパイルして色々弄っていけばいいんですが,いちいちコンパイルオプションを打つのは面倒です.
こういう時はMakefileを使うのがよくある手ですが,Nimでは他の方法があります.
main.nim.cfg
というファイルを作って,そのファイルにコンパイルオプションを列挙するだけでOKです.
コンパイルオプションは,--os:standalone
の他に,--gc:none
,--deadCodeElim:on
とかも付けておくと良いです.
あと,デフォルトのmain関数を作らない--noMain
,変換後のCコードをコンパイルしたオブジェクトファイルをリンクしない--noLinking
などもお忘れなく.
では,ちょっとコンパイルしてみましょう.
$ nim c main Hint: used config file '/etc/nim.cfg' [Conf] Hint: used config file 'main.nim.cfg' [Conf] Hint: system [Processing] lib/nim/system.nim(2708, 11) Error: cannot open '/home/sksat/prog/nim/nim-os/panicoverride'
失敗してしまいました.どうやら,panicoverride
というファイルが無いと言っています.
ここで,もう一度 Nim Compiler User Guide を見てみると,
For the standalone target one needs to provide a file panicoverride.nim. See tests/manyloc/standalone/panicoverride.nim for an example implementation. Additionally, users should specify the amount of heap space to use with the -d:StandaloneHeapSize=
command line switch. Note that the total heap size will be * sizeof(float64).
とあります.panicoverride.nim
を作らないといけないみたいですね.
とりあえず空のファイルを作ってコンパイルしてみると,
$ nim c main Hint: used config file '/etc/nim.cfg' [Conf] Hint: used config file 'main.nim.cfg' [Conf] Hint: system [Processing] lib/nim/system.nim(2714, 12) Error: undeclared identifier: 'panic'
panic
という関数は必須のようです.
同様に,rawoutput
という関数も必要なようなので,とりあえず空の関数を作っておきます.
proc rawoutput(s: string) = return proc panic(s: string) = return
で,またコンパイルしてみます.
$ nim c main Hint: used config file '/etc/nim.cfg' [Conf] Hint: used config file 'main.nim.cfg' [Conf] Hint: system [Processing] Hint: main [Processing] Hint: gcc -c -w -w -I$lib -ffreestanding -O2 -Wall -Wextra -I/usr/lib/nim -o /home/sksat/prog/nim/nim-os/nimcache/main.o /home/sksat/prog/nim/nim-os/nimcache/main.c [Exec] In file included from /home/sksat/prog/nim/nim-os/nimcache/main.c:10:0: /usr/lib/nim/nimbase.h:482:13: エラー: 配列 ‘Nim_and_C_compiler_disagree_on_target_architecture’ のサイズが負です typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error: execution of an external program failed: 'gcc -c -w -w -I$lib -ffreestanding -O2 -Wall -Wextra -I/usr/lib/nim -o /home/sksat/prog/nim/nim-os/nimcache/main.o /home/sksat/prog/nim/nim-os/nimcache/main.c'
あー,これはターゲットが32bitなのにコンパイルに使用しているgccが64bit向けだから起きてるエラーですね.nimkernelみたいに別のコンパイラを使ってもいいんですが,面倒なので-m32
オプションをつけてしまいましょう.
Cコンパイラのコンパイラオプションを書き換えるのは--passc
オプションで出来ます.
$ nim c main Hint: used config file '/etc/nim.cfg' [Conf] Hint: used config file 'main.nim.cfg' [Conf] Hint: system [Processing] Hint: main [Processing] Hint: gcc -c -w -w -I$lib -ffreestanding -O2 -Wall -Wextra -m32 -I/usr/lib/nim -o /home/sksat/prog/nim/nim-os/nimcache/main.o /home/sksat/prog/nim/nim-os/nimcache/main.c [Exec] Hint: gcc -c -w -w -I$lib -ffreestanding -O2 -Wall -Wextra -m32 -I/usr/lib/nim -o /home/sksat/prog/nim/nim-os/nimcache/stdlib_system.o /home/sksat/prog/nim/nim-os/nimcache/stdlib_system.c [Exec] Hint: operation successful (5319 lines compiled; 0.254 sec total; 3.758MiB peakmem; Debug Build) [SuccessX]
--os:standalone
オプションを付けているので,stdlib_system.c
でincludeしているのはnimbase.h
だけになっています.素晴らしい.
さて,これでmain関数が出来たので,あとはmain関数をブートローダーから呼び出してあげればいいですね.
今回はちょっと遅くなっちゃったのでnimkernelのboot.Sを拝借しました.
boot.Sをアセンブルしてやると,必要なオブジェクトファイルが揃います.
$ as --32 boot.S -o boot.o
後はこれらをリンクして,バイナリを作ります.
$ gcc -T linker.ld -o main.bin -m32 -ffreestanding -nostdlib boot.o nimcache/main.o nimcache/stdlib_system.o
あとはQEMUで起動してみるだけです.((今回はマルチブート仕様に則ったバイナリになっているので,-kernel
オプションで起動できます.))
$ qemu-system-i386 -kernel main.bin
まだ何もしていないので何も起こりませんが,無事起動出来ているようです.
...と思ってnimkernelの画面描画のコード持ってきて動かしてみても失敗しました....何故...というかこれmultiboo 2じゃないんですか...
まあ,自分でコード書けってことですね.
あと,nimkernelについてはそもそもビルドが通りませんでした.これについてももうちょっと調べてみます.
ということで不完全燃焼なかんじですが今回はここまでにします.期末試験中だし.
NeoVim使ってみた
Vim好きだけどちゃんと使ってる???
はい,はてブやってくかって思ったのでやっていきます. 今回のはみなさん大好きVim*1のやっていきです.
僕はあいでーいーとかちょっとよくわからない(というか,マトモに動いてくれない)*2ので,プログラミングにはだいたいVimを使ってます.
ですが,今までは生のVimを使っていただけでした. これはVimmerとしてちょっとどうなのかと思われるかもしれませんが,実はマトモに.vimrcを書いたことがないです.
ということで(そろそろ環境ごとにちょいちょい違うのも嫌になってきたので),「Vimをちゃんと使うか」というお気持ちになってきたので,やります.
NeoVim入れてみた
さて,ここで気になってきたのがNeoVimとかいうやつです. ググってたら頻繁に目についたので.
次世代のVim?かっこいいやんけ使ったろ(適当). Luaとかがデフォルトで入ってるっぽいですね.良さ.
まずはNeoVimのインストールですね.
# apt-get install neovim Reading package lists... Done Building dependency tree Reading state information... Done E: Unable to locate package neovim
は?
はい.デフォルトのaptだと入りませんね. PPAを追加してやるといけますね.
$ sudo apt-get install software-properties-common $ sudo add-apt-repository ppa:neovim-ppa/stable $ sudo apt-get update $ sudo apt-get install neovim
これだとstableですがunstableにしてやると最新版ににるっぽいですね. でも,せっかくなので最新版をビルドしてみます.
$ git clone https://github.com/neovim/neovim $ cd neovim $ make CMAKE_BUILD_TYPE=RelWithDebInfo $ sudo make install
ここでMakeの時に「まけ」と打った貴方は負けです. はい,負けました.
んでもって色々と調べてみてちょいちょい.vimrc書いてたんですが,どうもこの世界には数々の素晴らしいプラグインといふものがあるっぽいですね. で,しかもそのプラグインたちの管理をするプラグインマネージャもあるとか. 良さそうなので入れてみますかね.
闇の力に目覚める
プラグインマネージャにもいくつかあるっぽいのですが,某はオワコンとのことで,dein.vimを導入してみます.
"Dark powered"...かっこいい...
ところでこの記事をはてブのエディタで書いていたらFireFox落ちて一部原稿が吹き飛びました. 反省して(Neo)Vimで書きます.
— 千種夜羽@ヴァネぽよ (@sksat_tty) 2017年11月12日
やはりVimで書くべきでした.反省します.
— 千種夜羽@ヴァネぽよ (@sksat_tty) 2017年11月12日
はい.
では,闇の力に目覚めていきましょう. なんかQiitaのよくわからん記事見ながらほげほげしてたら失敗したので公式見ながらやります.
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh $ sh ./installer.sh ~/.vim/dein
こんかなんじにやると,installer.shがいいかんじに最低限必要な.vimrcを吐いてくれるので,.vimrcにコピペします.
あとはNeoVimを起動して,
:call dein#install()
とかしてやればok
と思いきや,ダメでした. 調べてみると,NeoVimにおける.vimrc的な奴は~/.config/nvim/init.vimとのこと. ということで,~/.config/nvim/init.vimにさっきのやつをコピペして,dein#install()してやると,うまくいきました.
というわけでNeoVimの方を使い始めていくので良さげな使い方とかプラギンとかあったら教えていただけると嬉しいです.はい.解散~w
最近の進捗(10月)
ひと月に一回くらい進捗記録しておくと良さそうなのでやる.
最近やったこと...なんだろう...夏休みがアだった*1のは覚えてるけど...
あと9月は文化祭がありましたね.夏休みがアだったので準備も割とアだったし色々とアなこともありましたが,うまくいったと思います.後輩も色々やってくれたので来年が楽しみですね.
さて10月の進捗ですが,プログラミング関連ではなんかlibsksatなるものを作ってました. これはなにかというと,C++のヘッダオンリライブラリ的なsomethingで,libslankdevとか,clxとか良さみが深いなあ,と思ってなんかほげほげしてました.
libsksatはなんか良さげ,と思ったクラスやらなんやらをとりあえずぶち込んでいくかんじrepoなので,再利用性があるかとかは微妙です. まあC++とgitの練習場みたいなものと思ってるのでいいんですけど(ブランチモデルとか最近知った顔). 使えそうなのができたらemu*2で使おうかな.
あとなんかあるかな...あった. そうそう,Redmine立ててみました.Herokuに.
前はPFLabのイベントの時にちょまどさんにもらったAzureのサブスクリプションのやつでRedmineのVM立てて文化祭とか某で使おうとして全然使ってもらえなかった使ってたんですが,あのときはbitnamiでシュッとやったのでRuby on Railsがどうとかはよく分からないまま使ってました.
で,そろそろサブスクリプション切れるし別の立てるか,みたいなノリで色々調べてやってみたはいいものの,動いたと思ったらInternal errorが多発してなんやお前,となったのでうーんうーんと唸りながらうまくいったやつをgistにまとめてみた次第. 大体rmagicとかDB周りで躓くっぽい.
せっかく立てたので有効活用していきたい(今の所某の別のやつで使ってる). あと,チョットRuby on Railsに興味持ったのでそのうちなんか作ってみようかな(などと
最近の進捗はこれぐらいですかねー(少ない). あとはせいぜいGASでslackにチームドライブの更新通知ぶん投げるやつ作ったり,sksat_botを334とか1333とか1640*3に反応させるようにしたぐらいか.
11月も進捗がnullじゃなければ書く.まあ何も無ければもくもく会のこととか書けばいいか(行ければだけど).