2014/12/07

自作OSでのプロセス実装について (2) ~初めてのユーザプロセス~

この投稿は Aizu Advent Calendar 2014 の 7 日目の記事です。

前の人 @masaponto
次の人 @MiZuKi_Sonoko

また、自作OS Advent Calendar 2014 の 7日目の記事でもあります。


自作OSでのプロセス実装について (1) ~初めてのユーザプロセス~の続きです。

前回の内容
  • プロセスとは?
  • x86リングプロテクション(ユーザモードとカーネルモード)
  • マルチタスク
  • 割り込み
  • コンテキストスイッチ
を一気に説明しました。
正直、多少知識が無いとわからないよなあって感じになっているのでその点は反省しております。

今回は

  • コンテキストスイッチの実装
  • ユーザプロセス起動

を見て行きたいと思います。

前回はタイマ割り込みによってコンテキストスイッチが起きる、というところで終わったと思います。
そこの流れが大事ですので再掲します。

タイマ割り込み発生
実行中プロセスは割り込まれる
(中断される)
カーネルモード突入
今のカーネルモードスタックへ
今の実行コンテキストを保存
(CPUのレジスタとか)
次のプロセスを選ぶ
次のカーネルモードスタックから
次の実行コンテキスト復元
ユーザモードに復帰
はい、こんな感じです。
(※カーネルスタックではわかりづらいのでカーネルモードスタックに変更します。)

では、早速ですがもぷりんOSのコンテキストスイッチ実装を見て行きましょう。
この部分は主にLinuxの実装を真似ています。
と言っても、x86上で同じことをやろうとしたら大体こうなると思います。。。

リポジトリはこちら
mopp/Axel

上記の流れに沿ってコードを掲載していきます。
まずは、一番はじめに呼ばれる割り込みコードを見てみましょう。
以下のこれは、割り込みエントリ関数で、タイマー割り込み以外のキーボード割り込みや一般保護例外などでも呼ばれる部分です。

上記コードはsrc/interrupt_asm.asmにあります。
ただし、Gistに貼った方は見やすさのためにマクロなど全て展開済みです。

レジスタ操作があるのでC言語では書けません。ですのでアセンブラを使用しています。
asm_interrupt_timerという関数がカーネル初期化時にCPUのタイマ割り込みハンドラに登録されます。
ですので、タイマ割り込みが発生したらCPUが勝手にasm_interrupt_timerを呼び出してくれます。

ここで大切なのは、割り込みが発生した際、CPUが自動的にカーネルモードに切り替えるということです。
これは前回も書いたかもしれないですが、きちんと書いていないので、ちゃんと説明します。
詳細は、仕様書: IA-32 インテル ® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル 下巻:システム・プログラミング・ガイドの5.12.1を参照してください。
同じことを書いています。

割り込まれる状況というのは、カーネルモード時割り込みとユーザモード時割り込みが有ります。
前回、スタックも切り替わると書きましたが、これはユーザモード時割り込みの時だけです。
そもそもとして、カーネルモードだったら、カーネルモードスタックになっているに決まってるんだから切り替える必要はないですよね。

以下の図を見てください。
ユーザモード時割り込みのスタック切り替え
以前動作していたコンテキストの一部がカーネルモードスタックに保存されます。
ここで特に大事なのは、eip, cs, esp, ssですね。割り込みから戻るときにこれらを使って戻ります。csとssを説明する気力がないのでWikipediaに投げます…
ここは、混乱しがちですので注意してください。
割り込まれた時のスタックでは無く、カーネルモードになってからのスタック(カーネルモードスタック)です。
カーネルモード時割り込みの場合は、以前のespとssは変わらないから不要ですので、error codeからeflagsまでがカーネルモードスタックに保存されます。

さて、asm_interrupt_timerに戻りましょう。
まず、タイマ割り込みにはエラーコードが無いので擬似的に設定します。
これは後々出てくる構造体のためです。
次に、割り込み前の状態を維持し、正しく復帰するために汎用レジスタなどを保存します。
そして、タイマ割り込みハンドラ本体を呼び出します。
この時に、pushしているespを、"後々出てくる構造体のポインタ"として、関数に渡しています。

本体の処理が終わったら、レジスタ状態の復元と擬似エラーコードの削除をします。
一番最後のiret命令これが、割り込み復帰処理です。
正しく元々実行していたところへ帰ってくれます。
その際、以前のespやeipが必須になるわけです。

次にinterrupt_timer関数ですが、これはsrc/time.cにあります。
でも、実際、下記の関数を呼び出しているだけなので省略。

上記コードはsrc/proc.cにあります。

このコードでは、プロセスの切り替えを行っています。
スレッド実装したかったので、プロセス構造体無いのスレッド構造体に色々入っています。

currentが現在実行中のプロセスで、nextに実行可能なプロセスを持ってきます。

ここでキモなのは、インラインアセンブラの部分です。
30, 31行目で現在プロセスが復帰した時のeipとespを保存しています。
なので、次に実行されるときは、next_turnから実行されることになります。

次に、切り替え先プロセスの情報を復元します。ここが一番大事です。
34行目でespを切り替えています。
これはまあ普通ですね。

次はeipを切り替えます。
ですが、eipに対してmov命令を実行することは出来ません。
なので、スタックに入れて、やります。
そして、call命令ではなくjmp命令で関数に移動します。
すると、関数の終了時にはret命令が呼ばれるはずです。
この、ret命令はスタックから戻り先アドレスをeipに復元します。
これを利用しています。
なので、change_contextから戻った時点で、既にプロセスは切り替わったことになります。

なお、ここでchange_contextに渡す引数はレジスタ渡し、fastcall規約で渡しています。
(Linuxのを真似してみたんですが、現状fastcallである必要はあまりない…)

今の流れを延々と繰り返して、マルチタスクが実現されているわけですね。


やっとコンテキストスイッチの説明が終わりました。(長すぎた)
初めてのユーザプロセス起動を見て行きましょう。
上記コードはsrc/proc.cにあります。

この関数はプロセス初期化中に呼ばれます。
まず、プロセスを一つ確保します。
そして、textセグメントとstackセグメントを確保します。(dataセグメント忘れてた…)

この次の15行目、これがポイントです!
thread.ipにinterrupt_returnを設定しています。
先のswitch_contextではthread.ipを次の復帰先として、使っていました。
つまり、このプロセスは次にswitch_contextによって切り替えられた時に、interrupt_returnから実行が始まるのです。
そして、interrupt_returnでは汎用レジスタの復元、そして、iret命令を実行しています。
iret命令では上図(ユーザモード時割り込みのスタック切り替え)のようなスタックを読み取ってユーザプロセスを再開しています。

つまり、あたかも割り込みから戻ったようにカーネルモードスタックを調節してやればいいのです!

18〜32行目でそれを行っています。
ここで使っているInterrupt_frameが後に出てくる構造体です。
これを使って、割り込み時のスタックをいい感じに参照、変更することが出来ます。
eip, prev_espが上図の前の〜〜に対応するものです。
これをプログラムの実行開始アドレスにしてやればいいわけです。
もぷりんOSの現在のinitプログラムでは実行開始アドレスはDEFAULT_TEXT_ADDRです。
この辺は実行プログラムによります。

そして、48行目で、switch_context内のnext_procで拾えるように、実行可能状態にします。

あとは、普通にスケジューラが動き出すのを待つだけです。
初期ユーザプロセスの起動はこれで完了になります。


時間があれば、forkとかexecの話ももっとちゃんと書きたいなと思っています。
それでは。

2014/12/05

自作OSでのプロセス実装について (1) ~初めてのユーザプロセス~

この投稿は Aizu Advent Calendar 2014 の 5 日目の記事です。

前の人 @i__yahoo
次の人 @masaponto

また、自作OS Advent Calendar 2014 の 5日目の記事でもあります。

Aizuの方に登録してたのですが、ネタ的に自作OSだし、自作OSカレンダーの方は空きが激しいので、まとめて登録してしまいました。
今回は自作OS Advent Calendar的に先日の記事の続きみたいなものです。
また、ALTで話した内容をもっとわかりやすく書いたものです。(次回のALTもあるらしいので興味のある人はぜひに)


この記事では、もぷりんOSの現在の実装における観点から話を進めていきますので、LinuxなどのOSとは異なることもあると思いますので注意してください。
特にもぷりんOSは権限周りなどがまだまだですし、私もよくわかって無いことが多いです。それだと危なくない?みたいなことがめっちゃ有ります(つまり、吹けば飛ぶ)
それに、趣味で楽しいからやっていることです。(だからといってセキュリティを軽視しているわけではないです。安心安全もぷりんOSを目指しますよ)
なので、あんまり細かいことは言わず、こんな風に書いてれば動くんだふーん程度の気持ちでお願いしたいです。
そして、何より自作OSを作ってる人、少し興味を持ってる人が見て、こんなの俺でもできるじゃねーかと感じて、自作OS作成してくれればなあと思いつつ書いていきます。


さてさて、本題に入るその前に、通常話しているプロセスについていくつか事前知識として、さらっと話そうと思います。
詳しいことはプロセス-Wikipediaにどうぞ
大雑把に言うと、プロセスは実行されているあるプログラムのことです。
もぷりんOSは一応?UNIX系のOSなので、ここでいうプロセスはUNIX系のプロセスを指しています。UNIX系プロセスは親子関係を持ちます。この親子関係というのはデータ構造で言うところの木構造で、大体こんな感じです。
数字はプロセスID(pid)を表します。
プロセス0がルートプロセス、その子プロセスがプロセス1
この時、プロセス1から見れば親はプロセス0になります。

当たり前ですが、プロセスの生成と削除はOSでは頻繁に行われます。
例えば、目の前のターミナルでlsコマンドを実行したとしましょう。
その瞬間、シェルが子プロセスlsを生成し、lsが実行されます。
色々表示した後に、lsは終了し、プロセスは削除され、元のシェルに戻るというわけです。
ここで、シェルのプロセスの親は何でしょうか、更にその親は?それのまた更に親は?
という疑問が湧いてきます。

と、いうことで本題です。
上図のルートプロセスであるプロセス0とその子であるプロセス1の話です。
プロセス識別子-Wikipediaからの引用ですが、
Unix系OSでは、プロセス識別子 0 と 1 は特別なタスクを指している。プロセス識別子 0 は swapper または sched と呼ばれ、ページングを担当している。これは実はカーネルの一部であり、ユーザーモードのプロセスではない。プロセス識別子 1 は init プロセスで、主にシステムの立ち上げとシャットダウンを担当している。
と、言うわけです。

もぷりんOSでもプロセス0はOSカーネル自体の事を指します。
ハードウェア(CPU,ディスク,マウス,キーボードなど)の初期化を主に行っています。
それらの初期化を終えた後に初めてのユーザプロセスであるプロセス1を立ち上げるわけです。

ここで、ユーザモードという言葉が出てきました。
これは大事です。テストに出ます。
このモードというのはIntel CPUの持つリングプロテクションのものです。
もぷりんOSはx86のみのサポートなのでこれ以降、x86前提で話していきます。
カーネル管理下の領域にはハードウェア情報やらなにやらがあり、誰でもアクセス可能だったら、めちゃくちゃ困りますし、セキュリティもあったもんじゃありません。なので、カーネルとユーザを分離する必要があります。そのための機構がリングプロテクションで、以下のような図で表されます。

x86リングプロテクション
数字が小さいほうが権限が高く、大きい方が権限が低いです。
x86では4つのリングがありますが、もぷりんOSでは0と3しか使っていません。
LinuxやFreeBSDも基本的に同様です(XenでRing1を使うとかなんとかあるらしいですが)
そして、このRing0をカーネルモード、Ring3をユーザモードと言っています。
このリングは外側のリング領域全てにアクセス可能です。
つまり、Ring0なら全てにアクセス可能で、Ring3なら外にはもう無いので、自分自身だけです。
カーネルはユーザに干渉できて、ユーザはカーネルに干渉出来ないことなります。
この機構はOSの基本的なセキュリティにぴったりですね。

と言ってみましたが、全くアクセス出来なくてはそれはそれで困ります。
上記で既に言ったように、カーネル領域にはハードウェア情報などがあります。
全くアクセス出来ないのではユーザプログラムはハードウェア資源を使えないことになってしまいます。ですので、一定の手順を踏むとユーザモードからカーネルモードに切り替わることが出来ます。イメージとしてはリングの内側にジャンプする感じですね。
そして、そういったカーネルプログラムをユーザプロセスが実行出来るようになるわけです。そのためのインターフェースがシステムコールというやつです。
ユーザプログラムはシステムコールを発行し、リング内側のカーネルに使いたい機能を要求して、色々と処理をしていくわけです。このとき、実行中プロセスはユーザプロセスですが、実際に動いているのはカーネルプログラムなので、OSが処理をしているのと変わりません。


かなりてきとうですが、大まかにユーザモードとカーネルモードについて説明しました。
話を戻しますと、起動時にはカーネルしか無いわけです、ユーザプログラムは一切存在しません。つまりカーネルモードプロセス一個のみです。
そして、今やりたいことは、それとは別のユーザプロセスを起動することです。
ここで暗に言っていますが、別のプロセスを起動することは、2つのプログラムを並列実行させることです。
これは何を隠そうマルチタスク-wikipediaです。
一般的に、CPUの計算処理時間に比べ、ディスクやネットワークの処理時間は数十から数百倍かかる。シングルタスク環境では、逐次処理が行われるため、入力待ちや通信待ちなど、CPUが計算を実行できずに、待つ時間が発生する。マルチタスクの導入によって、これらの待ち時間の間にCPUを動作させ別の計算を行い、全体の処理時間の短縮を実現することが可能になる。
またもやWikipediaからの引用です。
別の計算を行うということが、つまり別のプロセスに切り替えるということです。
この切り替えることをコンテキストスイッチと言います。
CPUの持つ汎用レジスタ(eax, ecx, ebx, edx)や現在のスタック(esp)やインストラクションポインタ(eip)などのコンテキストを全て切り替えるためにコンテキストスイッチと言われます。もちろん、それを実行出来るのはカーネルモードのみです。
図にしてみるとわかりやすいかと思います。
プロセスがいっぱいあるときも同様です。

もぷりんOSにおいて、コンテキストスイッチはタイマー割り込みによって生じます。
上記リンクのプリエンプティブ・マルチタスクというやつです。
これはタイマー割り込みによって、一定時間が経過すると、次のプロセスに切り替わる処理が実行されます。また、割り込みの処理をするもの(割り込みハンドラ)は全てカーネルが提供するものです。ゆえに、この時、実行していたプロセスはカーネルモードに切り替わって、コンテキストスイッチを実行します。
具体的には10ms秒ごとに割り込まれます。結構早いように思えますが、CPUの周波数からすればある程度プログラムを実行するには十分です。
コンテキストスイッチの流れを以下に図示します。
これはかなり重要です。マルチタスクの肝と言ってもいいでしょう。
以下の流れで動作します。

タイマ割り込み発生
実行中プロセスは割り込まれる
(中断される)
カーネルモード突入
今のカーネルスタックへ
今の実行コンテキストを保存
(CPUのレジスタとか)
次のプロセスを選ぶ
次のカーネルスタックから
次の実行コンテキスト復元
ユーザモードに復帰

ここで出てきた、プロセスのカーネルスタックとは、それぞれのプロセスがカーネルモード時に使用するスタックのことです。
先程は説明しませんでしたが、カーネルモードに切り替わるときに、スタックもカーネルスタックに切り替わります。またユーザプログラムのコンテキストも退避されます。これはx86の仕様です。上で同じことを言いましたが、雰囲気としてはカーネルに化けるような感じかなと思っています。なお、カーネルスタックはプロセスを生成する過程で設定されます。
ここで、この一連の割り込みの流れを、ユーザプログラムの立場から見ると、割り込まれた時、カーネルプログラムに移り、処理再開される時にはきっちり割り込まれた部分から再開するので、割り込まれたことすらわかりません。これによってユーザはマルチタスクのことなど気にせずにプログラミングができるし、我々も普段からしているというわけです。
やってみるとわかりますが、当たり前の事のように行われているのに裏では大変なんだなとしみじみ思います。



さて、だいぶ長くなってしまいました、疲れてしまったので今回の記事はここまでとします。思ったより大変な記事になりそう…
(2)も数日中に書いて公開します。

2014/12/03

[自作OS Advent Calendar 2014] 自作OSの紹介的なの

この記事は「自作OS Advent Calendar 2014」3日目の記事として書かれました。


まずはじめに、上記リンクを見ていただければ直ぐにわかりますが、自分が主催にもかかわらず1,2日が空きで書いてないです。これについて申し訳ありません。(言い訳ですが多忙につき書いていられませんでした)。

さて、とりあえず、何でもいいから書かないと始まらないということで、3日目として、現在開発中の自作OSの紹介的な話をしたいと思います。

開発リポジトリはこれ
https://github.com/mopp/Axel



名前は"Axel"と書いて、"あくせる"と呼んでいます。
通称"もぷりんOS"です。(余談だけど、Mopris(もぷりす)って案もあった)
イメージカラーはメタリックレッドです。この時点で、名前の由来がわかる人にはわかるかもしれませんね。

きっかけとしては、元々Linuxとかの中身が気になっていたということと、自作OS入門を読んで作って見たいなーと思っていたからです。
あと、セキュキャンに応募して2回落とされているので、それも開発モチベーションとして一つあります。来年も応募します(来年で最後なので行きたいんですよかなり)

具体的な話に移ります。
この記事を書いている時点のOSスペックは以下です。


  • モノリシックカーネル
  • ソースコード長さ 8000 行
  • ソースコード容量 250 KB
  • 実行ファイル容量 105 KB
  • 対応アーキテクチャ x86_32
  • 最低動作メモリ 12MB
  • 使用言語 C, nasm
  • 参考OS Linux, FreeBSD, Unix v6, xv6, HariboteOS

実装されている機能は以下です。


  • 物理メモリ管理 (BuddySystem)
  • x86ページング
  • 仮想メモリ管理 (Two Level Segregated Fit Allocator)
  • 割り込み
  • PS/2マウス、キーボード
  • VBEグラフィック
  • ATAデバイスアクセス
  • FAT32/16 ファイルシステム
  • ACPI(シャットダウンのみ)
  • システムコール
  • ELF形式ロード (静的のみ)
  • プロセス管理 (fork, execのみ)
  • プロセススケジューリング(ラウンドロビン)

環境にはQEMUとBochsを使ってます。
Bochsはデバッガが良い感じなのでおすすめです。
スタック、レジスタ、ページテーブル、実行コードの逆アセンブル表示、MagicBreakなどかなり助かります。
実機でも動かして見ましたが、やはりエミュレータと違いなかなかうまく行かないし、デバッグもめっちゃつらいです。

開発は動かすことを考えて実装するときもあり、バグがあったり、未実装な部分(FIXMEやTODO)も多いです。
いまはプロセス周りを書いているので、やっとOS開発らしくなってきたなあと感じてます。

現時点の今後の予定としては、プロセス周りの作り込み、OS内部の抽象化(デバイスやファイルシステム)、システムコールの追加を考えています。

今日は以上です。
書く余裕が出来る限りカレンダーを埋めていこうと思っています。
話題は上のリストから拾って詳細を書こうかなと。
また、この程度の記事でも超OKなので自作OS気になるな〜って人は書いていただければ嬉しいです。
「自作OS Advent Calendar 2014」

2014/09/15

セキュリティ・ミニキャンプ in 東北 2014 に行ってきた話

タイトルの通り、9/13, 9/14に会津で行われたミニキャンプに参加しました。
その感想を書いていきたいと思います。
事前課題はオレオレSNSの脆弱性探しでした。

まず1日目ですが、各講師の講義を受けました。
中でも園田講師の「情報セキュリティの今そこにある危機」が印象に残っています。
サービス提供者の求める情報とユーザの持つ情報のどこまでが個人情報でどこからが個人情報ではないのか、また、単体では意味をなさない(個人情報足り得ない)ものでも、データマイニング的に複合化すれば様々なことを知ることが出来る。
なので、最近のスマートフォンに始まり、ウェアラブルデバイス(なんとかウォッチですね※妖怪ではない)が持つ情報などを駆使して、抽象的な人格コピーが可能になる日も近いのでは?事前に集積したデータから、その人が何かを感じて、思考となる前に機会側で推測することが出来るのでは?といった意見が大変興味深かったです。

続いて宮本講師による「情報セキュリティ人材は本当に不足しているのか?」でした。
この講義によると、2004年に登場したウィルスが未だに大量に報告されている、というものがあり、少々意外に思いました。ウィルス意外にも古い脆弱性はまだまだ残っているそうです。ただそういったものはアップデートや最新版を使えば何も問題無いケースが多いとのこと。
そして、情報セキュリティ人材は数万人規模で足りないらしいです。
情報セキュリティに携わっている人でも力不足な人も結構いるとか。

その後、少しの休憩を挟み、西村講師(イケメンだった)による「スマートフォンのセキュリティ概論」と「HTML5のセキュリティ」でした。
前者は「マルウェア」「リスクウェア」「脆弱性のあるアプリ」の3つについて詳しくお話しいただきました。
後者はHTML5に段々と移行していく中で、脆弱性を作りこまないようにするにはどうするかなど具体例も多くあってわかりやすかったと思います。
特に動的ページ生成部分にはDOM Based XSSさせないために注意が必要のこと。

最後に、LT大会がありました。
噂のらまっこ氏の「楽しいバグハントの世界」が人気を博していました。

大学での1日目の講義は終了し、晩御飯です。
どこで食べるのかと思っていたら、自分もたまに行く、「めでたいや」(かなりうまい)でした。


結構な量があり、苦しそうな人も何人か見受けられました。

宿泊場所は会津 日新館でした。
小学生の頃、一度だけ訪れたことがありますが、まさか泊まる場所があったとは。
そこでも、夜9時から、夜の部の講義を受けました。
竹迫講師による「脆弱性、指摘する人・される人、利用する人・賞金を稼ぐ人」では
脆弱性を発見した時に、どうやって報告するのか、また、脆弱性を探すぞ!となった時にどこまでが白でどこまでが黒になるのか、と言ったことでした。
ところが、案外グレーゾーンが多いようで、人によって白黒が別れる見たいです。


その後は寝るだけだったのですが、同じ部屋になった人と
事前課題の脆弱性探しをしました。
自分一人では(らまっこ氏のヒントありで)2つしか見つけられなかったのですが、協力して計4つ見つけられました。
そんな感じで、記憶では大体2時くらいに寝たはずです。


二日目は再び会津大に戻り、実際に手を動かす演習開始です。
まず、事前課題の脆弱性探しでした。

4チームに別れて行いました。各チーム名はらまっこ氏が名づけたそうな。
(ちなみに、事前課題にSQLInjectionの脆弱性は無く、というか別にSQLは使っていない。)

その後、各チームごとに見つけた脆弱性の発表をして、西村講師からの回答編でした。
XSS、CSRF、Web MeMessagingの脆弱性などなど、十数個の脆弱性があったようです。

その後昼食を挟んだ、最後の講義は竹迫講師による「攻撃検知システムを自作しよう」でした、本来はかなり時間をかけてやるものらしいですがだいぶ省略して2時間弱で行いました。
脆弱性のあるWebサイトに対するディレクトリトラバーサル攻撃をLinuxカーネルモジュールを使って防止してみるというもので、Linuxカーネルの話が出てきたので少しテンションが上がりました。
この講義はしっかりと長時間受けてみたいなあと感じました。
大学でもこういうのがアレば皆、嬉々として受けると思います。


以上、時間軸に沿ってミニキャンプを振り返ってみました。
そして、最後に宮本講師曰く
「何でも1万時間やればオーソリティを得られる。」
とのお言葉をいただきました。


今後も修行していきます。

2014/04/03

2014版 VAIO Pro (SVP1322A1J) で Arch Linux と Windows 8.1 を デュアルブートする

VAIO Pro 13インチを買いました。
こいつです


初めてのWindows8.1です。
そして、ひとしきり楽しんだ後はやっぱりLinuxを入れたいですね。
そんなときはArch Linuxがおすすめです。

しかし、VAIO ProにArch、もといLinuxを入れるのはなかなか手こずるようで
自分も苦労しました。
なので、メモ書きとして残しておきます。

さて、まずはWindowsを普通に起動してパーティションの縮小です。
自分はWindows 100GB, Arch 100GBくらいにしました。

この時に、高速スタートアップを無効にしておきます。
これをしておかないとインストールはできますがインストール後に一度Windowsを起動するとArchもWindowsも起動できなくなってしまいます。
場所は、コントロールパネル→電源オプション→カバーを閉じた時の動作の選択(左側)→シャットダウン設定の中にあります。
ここでチェックボックスのチェックを外しておきましょう。

基本的にはInstallation Guide (日本語)を参考に進めていきます。
インストール用のUSBインストールディスクを作ります。
isoからddコマンドとかで普通に作れば問題ないです。

そして、BIOS設定で
AT Support System: disabled
Secure Boot: disabled
External Media: enabled
に変更します。
更にブート順序をExternal Mediaを一番上にします。
これらを保存してUSBを挿した状態で起動するとUSBからブートすることができます。
この時に稲妻マークのUSBポートだとうまくできないとかなんとか。

さて、ここで大事なポイントがありまして、ブートローダのオプションとして
一瞬の選択画面で"e"を押して、libata.force = noncqを追加してください。
これがないとSSDがエラーを起こしてすごく遅くなります。

起動後に縮小してできたあまりのエリアをgdiskで切り分けましょう。
gdiskはfdiskのGPT版らしいです。
そのあと、
% mkfs.ext4 /dev/sdaX
のようにフォーマットに掛けます

Arch用のパーティションは/と/homeに分割します。
また、デュアルブートするのでWindows用に標準で存在するEFIパーティションシステムであるsda3を/bootとして使用します。

そしたらマウントです。
自分の環境だとこんなんでした。
このときhomeとbootは無いので作成します。
% mount /dev/sda7 /mnt
% mount /dev/sda8 /mnt/home
% mount /dev/sda3 /mnt/boot
で、ここで無線LANを接続します。
% wifi-menu
を使うと簡単につなげます。

インターネットに接続できたのでこれからインストールするミラーをより早いところに接続するようにします。
% cd /etc/pacman.d/
% cp ./mirrorlist ./mirrorlist.original
% rankmirrors -n 5 > ./mirrorlist
次にArchのベースシステムをインストールします。
この時、再起動してからwifi設定できるように2つのパッケージを追加で指定しておきます。
% pacstrap /mnt base base-devel dialog wpa_supplicant vim
しばらく時間がかかるので放っておきましょう。
これが終わったらfstabを設定します
genfstab -U -p /mnt >> /mnt/etc/fstab
USBブート環境はここまでです。

% arch-chroot /mnt
を実行してインストールした新しい環境に切り替えましょう。

切り替え後は、まずHostnameを設定します。
適当なエディタで
% vim /etc/hostname
を編集して好きな名前を設定しましょう。

そして、タイムゾーンを日本にします
% ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
言語も日本語を有効にしておきましょう
% vim /etc/locale.gen
でen_US.UTF-8とja_JP.UTF-8のコメントアウトを解除します。
そしたら
%locale-gen
をして反映させ、
%/etc/locale.conf
LANG="ja_JP.UTF-8"と書き込みます。
次にrootのパスワードを設定します。
% passwd

さて、ここからが大事なところです。
ブートローダにはgrubを使用します。
% pacman -S grub efibootmgr
% grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub --recheck
これで/bootにgrubの設定ファイルもろもろができます。
そして、冒頭で設定したブートオプションをgrubにも追加します。
% vim /etc/default/grub
で開いてGRUB_CMDLINE_LINUX_DEFAULTlibata.force=noncqを追加します。
% grub-mkconfig -o /boot/grub/grub.cfg
次にブート時に読み込まれるWindwos用ファイルをgrubが生成したものに差し替えます。
この時、元のファイルは控えて起きます。
% cp /boot/EFI/Microsoft/Boot/bootmgfw.efi /boot/EFI/Microsoft/Boot/bootmgfw.efi.original
% cp /boot/EFI/grub/grubx64.efi /boot/EFI/Microsoft/Boot/bootmgfw.efi
実際、この辺自分もよくわかってないのですが、VAIO Proは手が加えられているようで
普通のUEFIのファイルとは場所が違うそうです。
それが原因ですんなり起動できないのかなーと。

はい、とりあえず、ここまででArchの起動は可能です。
しかし、grubにWindowsが表示されないです。(される人もいるとか)

ですので、grubのメニューエントリを追加しましょう。
% grub-probe --target=fs_uuid /boot/EFI/Microsoft/Boot/bootmgfw.efi.original
>> AEF2-4537

% grub-probe --target=hints_string /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi.original
>> --hint-bios=hd0,gpt3 --hint-efi=hd0,gpt3 --hint-baremetal=ahci0,gpt3
この2つの出力結果を以下のように/etc/grub.d/40_customに追記します。
menuentry "Windows 8" {
    insmod part_gpt
    insmod fat
    insmod search_fs_uuid
    insmod chain
    search --fs-uuid --set=root --hint-bios=hd0,gpt3 --hint-efi=hd0,gpt3 --hint-baremetal=ahci0,gpt3 AEF2-4537
    chainloader /efi/Microsoft/Boot/bootmgfw.efi.original
}
で、grubの設定を更新します。
% grub-mkconfig -o /boot/grub/grub.cfg
これで一番下にWindows8という項目が追加されたかと思います。

デュアルブートについてはこれで以上です。

おまけとして、無線LANの設定を書いておきます。
wifi-menu -o
を実行して、無線LANを有効可します。
このときに自動で/etc/netvtl/SSID名というファイルが作成されます。
このファイルにハイフンが含まれていると良くないので適当に名前を変えておきます。
そして、
% netctl enable 変えたSSID名
とすると次回起動時から自動で接続してくれます。
ここに書いたのはとりあえずなやり方なのでnetctlのページを見ることをおすすめします。


以下、参考にしたURLです。
大変助かりました。ありがとうございます。

2014/03/13

lightline.vimのバッファ履歴表示コンポーネントをかいた

この記事は Vim Advent Calendar 2013 103日目の記事になります。

今回はlightline.vimのコンポーネントを作ってみました。
基本的な部分については作者様直々に記事を執筆していらっしゃるのでそちらを参考にしてください。

普段Vimを使っていてバッファ一覧が常に見える位置にあるのは何かと便利です。
ちらっと見てから、直ぐに:b2とかで移動できますからね。

ですが、あまり場所を取ってほしくはありません。
それに、ただのバッファ一覧ではなくてVimFilerとかUniteとかのバッファは除外してほしい。
しかも、開いた順に表示したい。

そこでlightline.vimのコンポーネントを書きました。


ぜひ活用してやってください。
また、バグがあれば気軽に教えて下さい。

2014/03/04

Vim で .c/.cpp と.h/.hpp とかを相互に開くPluginをつくったじゃんよ

この記事は Vim Advent Calendar 2013 94日目の記事になります。
はい、今回は自作Pluginの紹介です。

mopp/next-alter.vim


自分は、ねくすとおるたーと呼んでいます。
このプラギンは対になるファイルをササッと開くためのプラギンです。
同様なプラギンはあったのですがうまく動かなかったので作りました。

具体的に説明をしていきましょう。
みなさんも実装ファイルをいじっている時にヘッダを開きたくなるのはよくあるはずです。
例えば、"hoge.c"をエディット中にそれと対を成す"hoge.h"を一瞬で開くことができます。

動作例は以下です。


このプラギンは以下のコマンドとマッピングの2つを提供します。
:OpenNAlter
<Plug>(next-alter-open)

また、開くときに縦に開きたいとか横に開きたいとか、その日の気分によって変わります。
そんな時のために、コマンドはオプションで開き方を変更することができます。
便利ですねー(かなり)

マッピングでは、以下の変数に設定しておくことで動作を変更可能です
let g:next_alter#open_option = 'vertical topleft'
詳しくはgithubのREADME.mdを見てください。
さて、次はどんなプラギンをつくろうか…

2014/02/28

君の知らないVimレジスター

この記事は Vim Advent Calendar 2013 90日目の記事になります。

どうも、一足早い春休みに突入したもぷりです。
しかし春と言っても、まだまだ、寒いですねー。
先日からneovimの話題でもちきりですが、Vim本体についての紹介です。


今回はレジスタの話です。
まずは、ヘルプを見てみましょう。
:help registers
レジスタには 9 種類ある: *registers* *E354*
1. 無名レジスタ ""
2. 10個の番号付きレジスタ "0 から "9
3. 小削除用レジスタ "-
4. 26個の名前付きレジスタ "a から "z または "A から "Z
5. 4個の読み取り専用レジスタ ": と ". と "% と "#
6. expression 用レジスタ "=
7. 選択領域用レジスタ "* と "+ と "~
8. 消去専用レジスタ "_
9. 最終検索パターン用レジスタ "/

意外と種類がありますね。
詳しくはそのままヘルプを読めばわかると思います。

そして、このレジスタはなんとインサートモードから呼び出すことが可能です。
やり方はインサートモードで
<C-R> レジスタ
です。


これを使ったテクニックを紹介します。
まずは、実践Vimにも記述されているものです。
<C-R>={何か式}
インサートモードにて入力すると、コマンドモードに=が現れて続けて入力ができます。
例えば、四則演算などの簡単な式を埋め込みたいときなどに有用です。
メモリアドレスの計算なんかしたいときなど
「<C-R>=0xA000 - 0x0909」と打てば「38647」と表示されます。
おっと、これは10進数です。メモリアドレスなんだから当然16進数がいいですね。

ここで、入力できるのは計算式ではなくVimにとっての式であるというのが便利ポイントです。
「<C-R>=printf('0x%x', 0xA000 - 0x0909)」とすると「0x96f7」で入力されます。


次によく使うのは「*」と「+」レジスタの2つです。
このレジスタはシステムのクリップボードの内容を表します。
<C-R>+
これでブラウザなどからコピペできますね。
ターミナルなどを使っていて、普通にインサートモードでコピペを使用とすると、
インデントやPluginなどが動作して崩れる場合があります。
MacとWindowsでは2つは同値らしいですが、Unixでは「+」を使ってください。

これはかなり便利なのでマップしておいたりすると便利です。
逆にシステムクリップボードにヤンクするにはノーマルモードで
「"+yy」でできます。これもマップしておくとよいですね


次には、何かした時に「あー、今のやつをテキストとして入力したい」ということがあると思います。
そういう時に使うのが以下です。
編集中のファイル名 <C-R>%
直前のテキスト     <C-R>.
直前のコマンド     <C-R>:
直前の検索         <C-R>/
このあたりを使いこなすととても便利力があがりますねー


と、今日はここまでにしておきます。

2014/02/20

.vimrcでありがちなミスとかおすすめとか

この記事は Vim Advent Calendar 2013 82日目の記事になります。

\アドベント!/

今回は、みんなの大好きなvimrcの話です。
人のvimrcを見ているととても面白いですが、「あ、これはこうしたほうがいいよな〜」なんて思うことが稀にあります。

そんな間違いや個人的にこうしたほうがいいよって言うものをまとめて見ました。

1. ファイル形式別機能の有効無効設定

これはかなり頻繁に見かける間違いです。
間違い

filetype plugin indent on
filetype indent on
正しい

filetype plugin indent on 
これはhelpを引けばわかります。
:help :filetype-overview
有効無効の設定は一括でできます。



2. カラースキームとシンタックスの有効


これは自分もハマりました。

間違い
colorscheme mopkai
syntax enable
正しい
syntax enable
colorscheme mopkai
順番が大事なのです、逆にするとうまく色がつかない場合があります。
原因は不明です…



3. インデント

この記事を書いていて自分のvimrcのミスに気が付きました

間違い
set smartindent
set cindent

正しい
set smartindent
or
set cindent
これはこちらに書いてあります。
:help smartindent
smartindentはcindentかindentexprが有効なときは意味が無いようです。



4. nocompatible

set nocompatible
これはvimrcを書き始めたらまず書くと思います。
別に間違いではありませんが、これは不要です。
:help compatible
を見てみると、「既定では オン、ファイルvimrcまたはgvimrcが発見されたらオフ」とあります。
つまり、vimrcを書いた時点でnocompatibleになります。


5. 複数の設定値

set backspace=2
set autoindent
set cindent
set expandtab    
set shiftwidth=4
 
これは以下と同様です。
set backspace=2 autoindent cindent expandtab shiftwidth=4  
好きな方を書くといいと思います。
ちなみに自分は末尾にコメントを書くので前者が好きです。


6. 設定値の反転

これも意外と知られていないと思います。
set paste!
set invpaste
ペーストオプションのトグルを行います、2つは同じ意味です。
これをマッピングしておくととても便利です。


7. mapの違い
これはvimrc成長させはじめの人に見受けられます。
Vimのmapまず、「展開するmap」と「展開しないmap」に二分されます。
ちょうどいいので自分のvimrcのメモ書きを貼っておきます。
どのモードでマップするかも大事ですからね。
どうぞコピペしてください。


これのnoreが付いている方が展開しないほうで、ついていないのが展開するものです。
するものは、マップ先にマップされているものがあればそれも評価して実行します。
どちらを使うか考えながらマップしましょう。

2014/02/18

Vimの:makeの引数補完機能付き:Makeを作った。

この記事は Vim Advent Calendar 2013 80日目の記事になります。
書かぬなら、私が書こう、アドベント

はい、もぷりです。
今回も、自作Pluginの紹介です。

Vimには:makeというコマンドがあります。
意外と知らない人もいるかも知れませんので軽く説明を。

このコマンドはいろいろ設定出来るのですが、何も設定しない状態で実行すると

$ make

を実行したのと同じ動作をします。

つまり、Vimを終了せずとも自分で書いたMakefileを実行出来るわけです。
これだけでも結構便利ですね。

しかし、自分の環境では:makeはファイル名の補完しか行ってくれません。
Makefileは生成ファイル名を書くのだからこれでもまあ、悪くはないのですが

$ make clean
$ make all
$ make run

とかの.PHONYをつけるようなターゲットも補完してほしいわけです。

更に、READMEなどもファイルなので候補に上がりますが、個人的に出てきてほしくないです。

なのでPluginを作りました。
こちらです。


ちょっとわかりづらいですがこんなかんじで動きます。

これでmakeしやすくなりましたー