はじめてのOSコードリーディング #1 ことはじめ
UNIXカーネルなどの低レイヤなところに詳しくなりたい。 ずっとそんなことを思っていたので、「はじめてのOSコードリーディング」で勉強を始めた。
はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)
著者の@superhogeさんのブログ↓
「はじめてのOSコードリーディング」という本を出版します - やる気のないはてだ
@7shiさん主催の読書会にも参加してきたので、その内容も含めながら覚え書き。
UNIX V6ソースコードのダウンロード
ここがUNIXの歴史のトップページ。http://minnie.tuhs.org/cgi-bin/utree.pl
ソースコードのアーカイブはここから。http://minnie.tuhs.org/Archive/PDP-11/Distributions/research/Dennis_v6/
第1章: UNIX V6の全体像
カーネルとは?
OSの中核を成す部分。システムを構築するために必要な機能を提供する。
カーネルは、アプリケーションに対してH/Wの抽象化を行い、またシステムコールを提供する。アプリケーションプログラムは、システムコールを使ってカーネルに対して要求を出す。
システム管理機能をカーネルに集約・隠蔽することでセキュリティと保守性を保っている。 また、POSIXという移植性を高めるための規格がある。(Unix TSS 5〜6からPOSIXができてきたらしい)
Pre K&R C
UNIX V6はPre K&R Cで書かれていて、その記法にとてもクセがある。 プロトタイプ宣言なし、キャストなし。
キャストがないのでレジスタ操作は以下の様な無名構造体を用い、1ワードのデータをint型で無理やり読み出し、書き込みする。
PDP-11
UNIX V6を構成するプロセッサ。資料へのリンクを貼っておく。
- PDP-11 - Wikipedia
- PDP-11 Processor Handbook : プロセッサ詳細や命令セット調査で参照する
- PRP-11 Processor Handbook(PDF): twitterで@7shiさんに教えていただき追記
Vimビルド時のオプション
たぶん2度と思い出せなくなるのでメモ。
$ ./configure --prefix=$HOME/Garage/Toybox/ext --enable-FEATURE \ --enable-mzschemeinterp --enable-perlinterp=yes --enable-pythoninterp=yes \ --enable-python3interp=yes --enable-rubyinterp=yes --enable-cscope \ --enable-multibyte --enable-xim --enable-fontset --with-features=huge \ --enable-gui=no --with-local-dir=$HOME/Garage/Toybox/ext --disable-selinux \ --enable-luainterp=yes
tlibでncursesが必要なので、別途インストールする。 g++入ってないとncursesのビルドに失敗するよ!
$ sudo apt-get install libncurses5-dev libncursesw5-dev
参考
選択範囲に一括ペーストできる fitpaste-vim 書いた
Vimでは[ctrl-v]
のブロック選択からI
、またはA
を入力することによって、選択列の先頭もしくは末尾にテキストを一括入力することができます。
[ctrl-v]
でブロック選択して、
I
でテキスト入力。
[esc]
で抜けると、一括挿入!
これがとても便利で、よく活用しています。
では、これと同じことをペーストでやってみましょう。
貼り付けるテキストをヤンク。
[ctrl-v]
でブロック選択して、
P
でペースト!
あれ?なんだかおもったのとちがう…。
もっとね、こんな風になるのを期待しちゃうわけですよ。
ブロック選択していようがいなかろうが、Vimのデフォルトのペースト動作ではレジスタの中身をそのまま出力します。
ペーストする内容を選択範囲に合わせてくれるなんてことはしてくれません。
でも、一括挿入と同じような感覚でペーストしたいなぁ…。
ということで、Vimプラグインを書いてみました。
一括ペーストプラグイン fitpaste
https://github.com/ryochack/fitpaste-vim
このプラグインを使うことで一括ペーストが可能になります。
貼り付けるテキストをヤンク。
[ctrl-v]
でブロック選択して、
i
で挿入ペースト!
できた!
ちなみに、a
で追加ペースト、p
で置換が行えます。
(キーマッピングは変更可能)
地味だけど、ずっと前から作りたかったプラグインなのでこれから重宝しそうです。
VimScript覚書
はじめての、びむすくりぷと。
ってことで、ちょっとしたVimプラグインを開発中。
その過程でのVimScript覚書をメモ。
VimScript開発の取っ掛かりに参考にさせてもらったページ
Vimスクリプト基礎文法最速マスター - 永遠に未完成
Big Sky :: モテる男のVim Script短期集中講座
autoloadは、autoload/foo/bar/baz.vimの様にフォルダ階層で区切られたファイルが#でセパレートされたネームスペースで呼び出され、call foo#bar#baz#XXX()というアクセスの瞬間にbaz.vimが読み込まれるという仕組みを持っています。
ですので、最近のVim Scriptはpluginではコマンドやキーマップのみを宣言するのが最近の流儀です。
使いそうな組み込み関数
参考:
- mode({expr})
- 現在のモードを示す文字列を返す
'n' : ノーマル
'v' : 文字指定ビジュアル
'V' : 行指定ビジュアル
'CTRL-V' : 矩形指定ビジュアル
's' : 文字指定選択
'S' : 行指定選択
'CTRL-S' : 矩形指定選択
'i' : 挿入
'c' : コマンドライン - getreg( [{regname} [, 1]])
- レジスタの中身を取得
- getregtype( [{regname}])
- レジスタの種類を取得
'v' : 文字指定
'V' : 行指定
'<CTRL-V>{width}' : 矩形指定
0 : 空または未知レジスタ - line({expr})
- 行番号を取得
line('.') : カーソル位置の行番号取得
line('v') : ビジュアルモードでの選択領域の開始行番号取得 - col({expr})
- 桁番号を取得
col('.') : カーソル位置の桁番号取得 - virtcol({expr})
- スクリーン上での桁番号を取得
virtcol('.') : カーソル位置の桁番号取得 - getpos({expr})
- カーソル位置を[bufnum, lnum, col, off]のリストで取得する
{expr}の値はline()と同じ - setpos({expr}, {list})
- {expr}の位置を設定する
listの値は[bufnum, lnum, col, off]でなくてはならない
成功すれば0、失敗すれば-1を返す
自動コマンドautocmdについて
その他覚書
letは変数の定義時だけではなく、変数を扱う際にも付けなくてはならない
let a = 1 "定義” let a += 5 "値の変更" a += 5 "NG!"
関数を呼び出す時は変数への代入やcallコマンドを使用する必要がある
let a = Func() "OK" call Func() "OK" Func() "NG!"
関数にrangeを付加することで範囲を指定して呼び出せる
a:firstline/a:lastlineで範囲の開始行と終了行を取得できる
rangeなし関数で複数行選択中に関数を呼び出すと、各行毎に関数処理が行われる。
function! Func() range let lnum = a:lastline - a:firstline + 1 echo 'select line num =' . lnum endfunction