2015年12月13日日曜日

Qiita を試してみた

Blogger で記事を書いていて、やっぱり Markdown でさくさく書きたいなあと思ったので、Qiita を試してみました。

uchan_nos / 最近の投稿

Blogger は HTML と CSS を直に編集でき、柔軟性は高いです。しかし、そんなに柔軟性は要らないからもっとさくさく書きたい私にとっては、ちょっと使いにくいブログシステムでした。コードのハイライトも SyntaxHighlighter などの外部ツールを入れる必要がありますし。

Qiita なら Markdown で書けるし、デフォルトで様々な言語の色分けに対応しているしで、非常に楽ですね。ということで、今後は Qiita に記事を投稿していくことになると思います。よろしくお願いします。

【Ubuntu】ラップトップ PC の蓋を閉じてスリープさせる

LAVIE Direct HZ というラップトップ PC に Ubuntu 15.04 を入れて使ってる。この PC は 13.3 型もの大きさがあるのに非常に軽く、筆者のお気に入りだ。ただ、残念なことに蓋を閉じてもスリープモードにならない問題があった。

蓋を閉じてもスリープしない

蓋を開閉して dmesg を確認してみると、次のようなメッセージが出ることが確認できた。

蓋を操作するたびに "Unknown key pressed" が記録される。ラップトップの蓋のスイッチが開閉を感知すると、OS に対してあたかもキーボードが打鍵されたかのように信号を送るようになっているらしい。しかしそのキーを OS が知らないために解釈し損ねているというメッセージだ。

Configure unrecognized keys in Linux - Juan Valencia's website には、キーが打たれたときに何が起きるかが詳しく書いてある。簡単に説明すると、キーが打たれるとキーボードから「スキャンコード」が OS に送信され、OS が持つ対応表を元に「キーコード」へ変換される。先のエラーメッセージは、その対応表に登録されていないスキャンコードが送られてきたという意味だ。

蓋の開閉をスリープボタンに対応させる

エラーメッセージにもあるように、OS にそのスキャンコードがどのキーコードに対応させるべきかを教えるコマンドが setkeycodes である。蓋を閉じたときにスリープさせたければ、スキャンコード e02b をスリープボタンと同じキーコードに対応させれば良い。スリープボタンのキーコードは xmodmap コマンドを使って調べる。

$ xmodmap -pke | less

この中から XF86Sleep や XF86WakeUp というキーを探す。見つけたらそのキーコードを覚えておく。筆者の環境ではそれぞれ 150, 151 となっていた。

...
Keycode 150 = XF86Sleep NoSymbol XF86Sleep
Keycode 151 = XF86WakeUp NoSymbol XF86WakeUp
...

これが分かれば、後は setkeycodes コマンドで設定するだけだ。ただし、xmodmap で表示されたキーコードから 8 を引いた値を設定する必要があるようだ。

$ sudo setkeycodes e02b 142
$ sudo setkeycodes e02c 143

うまくいかないときは、試しにアルファベットのキーコードを設定して蓋を開閉してみて、ターミナルに文字が入力されるかを見てみると良いかもしれない。想定した文字が入力されるかを見れば 8 を引くべきかどうかを確認できる。

起動時に自動的に設定する

このままでは、PC を再起動すると設定が初期化されてしまうので、PC を起動するたびに自動的に設定を行うようにしたい。Ubuntu 15.04 では標準で systemd が起動時の処理を担当しているので、それに合わせて設定ファイルを書けば良い。

/etc/systemd/system/set-lid-keys.service
[Unit]
Description=Set Keycodes of LID Keys

[Service]
ExecStart=/bin/sh -c "setkeycodes e02b 142; setkeycodes e02c 143"
Type=oneshot

[Install]
WantedBy=default.target

systemd の一般的な説明は他に譲るとして、上記の設定項目を簡単に説明する。

  • ファイル名:普通のジョブを表す .service という拡張子を付ける。
  • Description:ジョブの説明文。
  • ExecStart:実行させたいプロセスを書く。絶対パスで書かないとダメらしい。
  • Type:oneshot は一度実行してすぐ終わるジョブを表す。
  • WantedBy:default.target は systemd が起動すると必ず実行されるターゲット。他には graphical.target なども有るが、どれが最適かは筆者は知らない。

設定ファイルが準備できたら、システム起動時に読み込まれるように systemctl コマンドで有効化する。

$ sudo systemctl enable set-lid-keys.service

これで設定は完了だ。

2015年9月27日日曜日

Joel on Software 読書のすすめ

皆さんは "Joel on Software"(日本語訳版『ジョエル・オン・ソフトウェア』オーム社) という書籍をご存知だろうか。この本は Joel Spolsky という人がソフトウェアに関わる様々なこと、例えば言語選択の方法、 Unicode についての基礎知識、良いプログラマの雇い方、非技術系マネージャの頭の中など、多岐に渡る話題に対して彼なりの考え方を書いたものだ。


この本について書評を書こうと思ったのは内容が非常に良かったからに他ならない。本の帯には「マネジメントの世界にようこそ!」とあるが、よくあるマネジメントに関する教科書のように(というか、マネジメントに限らず退屈な教科書によく見られることだが)無味乾燥な解説が並んでいるのではない。ユーモア溢れる文体で笑いながら読めるのである。技術書なのに、まるで落語家が喋っているかのように私は感じた。

例えば Unicode に関する章(*)には次のような段落がある。
私は宣言する。もしあなたが21世紀において仕事しているプログラマであり、キャラクタ、キャラクタセット、エンコーディング、Unicodeの基本について知らないのであれば、私はあなたをひっ捕まえて、潜水艦で6ヶ月間のたまねぎ剥きの刑に処する。絶対そうするから。
私はこれを読んだときゲラゲラと笑ってしまった。Unicodeに関する技術的な記事なのに、である。このように楽しい表現が本書の随所に見られ、Joel さんの文章力(人心掌握力)に感心するばっかりだ。私は日本語訳を読んでいるので、訳者の青木靖さんのユーモアセンスによる部分もあるかもしれないけど。

(*)「すべてのソフトウェア開発者が絶対確実に知っていなければならない Unicode とキャラクタセットに関する最低限のこと(良い訳なし!)」という章題からして面白い。

この本はLinuxのコマンドラインだとか、特定のプログラミング言語だとか、今流行の技術だとかについては解説しない。この本は、あなたがプログラムを作って売る会社で働く、またはそのような会社を経営するとして、どうすればビジネスとして成功するかを解説している。あなたがプログラマなら、古いクズコードを捨ててスクラッチから書き直したいと思ったことがあるだろう。ビジネスをする上で、それがいかに悪い戦略であるかを、プログラマなら誰でも納得できる理由とともに説明している。

私がお気に入りなのは「氷山の秘密、明らかに」という章だ。題名からは何の話だかまったく分からないが、つまりこういうことだ:プログラミング作業全体を氷山として見たとき、ユーザインターフェースに関する部分は水面に出ている10%程度でしかない。だから、UI以外の部分を作るのに全体のスケジュールの90%の時間がかかるのだ。そして「プログラマ以外の人々はこの事実を理解していない。(p.212)」

章題の面白さもさることながら、本文も筆者の体験を踏まえて非常にコミカルに書かれ、それでいて明日からさっそく役立ちそうな実践的な話になっている。顧客または非技術系マネージャがあなたのプログラムを見る時はUIしか見ないので、プロトタイプとして最初にほとんど完璧なUIを見せてしまうと、彼らはその時点でプログラムが完成していると思ってしまう。そして、残りの期間、「人々はあなたが何をしているのか分からず、何もしていないと思うのだ。(p.213)」

この本は次のような人におすすめする。

  • 趣味ではなく、仕事でプログラムを書く人
  • スケジュール管理をしたり、社長に進捗を報告する必要のある人
  • 会社を成功させるためにソフトウェアの開発・販売戦略を考える人

この本の主軸は、ビジネスとしてソフトウェア開発が成功する方法について、である。その世界では、高品質なソフトウェアをなるべく出荷することが正義であり、プログラマ生活を楽しく過ごすことが正義である。そのためにスケジュール管理や仕様書が大切であり、有能なプログラマを雇って集中できる環境を作ることが大切なのだ。

仕様書が大切だ、というと、あの堅苦しい、バインダー数冊分もある分厚い仕様書を書くなんて御免だ!と思うかもしれない。その通り。本書でいう良い仕様書とは、可笑しく、学術論文のように堅苦しくなく、箇条書き・挿絵・チャート・表・空白をたくさん使い、画一的なテンプレートには従わないで書かれた、プログラムの機能仕様書である。仕様書はその製品に関わるプログラマ、品質保証の人、マーケティングの人、マネージャなどが読むための文書であり、プログラマでない彼らが読もうと思える文書にしなければならない。本書には明日から実践できる具体的なルールが詰まっている。

ここでは仕様書に関する本書の内容を紹介したが、スケジュール管理の方法、有能なプログラマを雇う方法、彼らを集中できるようにする方法ももちろん書かれている。ソフトウェアを作って売ることに関係がある方・または将来関係を持つだろう方には、強くこの本をおすすめする。ああ、どうして、私がソフトウェア工学を学んでいた大学院生のときにこの本を読まなかったのだろう。

2015年8月30日日曜日

【自作エミュレータで学ぶx86アーキテクチャ】書店に並ぶ様子まとめ

書店での目撃情報などが出てきたので、ここにまとめます。

書泉ブックタワー

丸善 日本橋店

ジュンク堂 渋谷店

ジュンク堂 池袋本店

有隣堂 ヨドバシAKIBA店

2015年8月22日土曜日

日本語キーボードを US 配列で使いつつ、変換/無変換キーで IME ON/OFF

僕はキーボードのキー配列は US 配列が好きです。なぜなら記号の位置などが JP 配列より綺麗だからです。JP 配列ではなぜか離れ離れになっている「'」と「"」、「;」と「:」が同じキーに割り当てられていたりします。

でも US 配列のキーボードはちょっと嫌いです。なぜなら「変換」「無変換」キーがないからです。そんなキーは普段使わない、という人もいるかもしれませんが、この 2 つのキーはカスタマイズにちょうどいいと思いませんか。US 配列キーボードのスペースバーは長すぎて無駄だと思いませんか。

僕は「変換」を IME のオンに、「無変換」を IME のオフに割り当てて使うのが好みなので、それらのキーがある JP 配列キーボードは必需品です。半角・全角キーは「今、どちらの設定だったか」を覚えておく必要があって、半角モードにしたいのに間違えて全角になってしまってイライラするのですが、IME のオンオフを別のキーにしておくことで、ステートレスな IME 切り替えを実現できます。(Mac の JP キーボードは最初からそうなっていて素敵ですね)

問題は JP 配列キーボード(例えば REALFORCE108UBK)の大部分のキーを US 配列として使いつつも、変換・無変換キーを有効化して IME オンオフに使うにはどうするかということです。Windows で通常の手順(Windows 8 でキーボードが英語配列キーボードとして認識される)でキーボードレイアウトを「101 キーボード」にしてしまうと、変換・無変換キーが存在しない純粋な US 配列キーボードとして扱われてしまって問題を解決できません。

そこで AX 配列(参考:右Altキーに[漢字]キーを割り当てる方法 )を使います。AX 配列とは参考記事に書いてある通り、 US 配列に必要最低限の変更を加えて(つまり記号の位置などを極力変更せず)日本語環境で使いやすくした配列であり、今回の問題にピッタリなのです。

AX 配列への変更は参考記事を参照していただくとして、ここでは AX 配列に変更した後にやるとよいキー配置変更を説明します。AX 配列に変更してみると分かると思いますが、JP 配列キーボードの「}]」キー(Enter の左下)を押すと「\」が入力されてしまったり、「\|」キー(Back Space の左)を押しても何も入力されなかったりと、少し不便です。さらに重要なことに、変換・無変換キーを IME の切り替えに割り当てることができない状態になっています。

ということでレジストリの HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout に「Scancode Map」というバイナリ値を書き込みます。
この方法は日本語キーボードを英語キーボードとして使う - Nikepを大いに参考にしています。Scancode Map は実際に押されたキーをどのキーに変換するかを定義するもので、上図の値は具体的に次の設定を表します。

  • 1D,00,3A,00 : 3A (Caps Lock) → 1D (Ctrl)
  • 3A,00,1D,00 : 1D (Ctrl) → 3A (Caps Lock)
  • 1C,00,2B,00 : 2B (JP }] key) → 1C (Enter)
  • 2B,00,7D,00 : 7D (JP |\ key) → 2B (JP }] key)
  • 36,00,73,00 : 73 (JP _\ key) → 36 (Right Shift)
  • 38,E0,70,00 : 70 (JP kana) → E0 38 (Right Alt)
  • 5B,00,79,00 : 79 (JP henkan) -> 5B
  • 5A,00,7B,00 : 7B (JP muhenkan) -> 5A
5B、5A はどうしてその値なのか良く分かりませんが、とりあえずその値に変換すると変換・無変換キーを変換・無変換キーとして認識するようになります。後は IME の設定を変えるだけです。

IME のプロパティから「詳細設定」画面を開き、キー設定の「変更」をクリックします。
変換と無変換が押されたときの挙動を「IME-オン」「IME-オフ」に対応付けます。
以上で設定は完了です。快適なキーボードライフをお過ごしください!

2015年8月14日金曜日

出版のお知らせ 『自作エミュレータで学ぶx86アーキテクチャ』

久しぶりのブログ更新となりました。
理由の一つは、ここ数ヶ月は暇さえあれば本の原稿を書いていたからです。

本のタイトルはちょっと長いですが
『自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!』
ということになりました。
8月28日に出版予定でございます。



2015年8月23日更新
Kindle 版が 2,152円+税で予約開始したようです。
自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!


共著の方(d-kamiさん)のブログでも紹介されています。
というわけで本を出版します - マイペースなプログラミング日記

タイトルの通り、この本はx86 CPUの機械語を実行するエミュレータソフトウェアを作りながらx86アーキテクチャを学んでいこうという本です。例えばinc [ebp-4]を機械語に変換するとff 45 fcになり、それぞれがオペコード、ModR/M、ディスプレースメントに対応することを学びます。ModR/Mの中も実はビット単位で意味があり、Mod、REG、R/Mに分かれているんだよという話もします。

2015年8月25日更新:
本書で作るエミュレータは x86 の中でも一部の機能を実装したとてもシンプルなものです。一言で表せば、オペランドサイズが 32 ビットのリアルモードエミュレータです。リアルモードの全命令を実装しているわけではありませんし、セグメント機構など高度な機能も実装しませんが、それでも C 言語で書いたプログラムを動かすことができるくらいの機能は持っています。人によっては物足りなく感じる方もいらっしゃると思いますが、本書は C 言語を学び終えたくらいの人が次に読む本を想定していますのでご了承ください。

CPUに閉じることなく、CPUとその周りとの関連も扱っています。x86 CPUはメインメモリにスタック構造を作ります。C言語入門した直後だとそもそもスタックを知らないかもしれませんので、一般的なスタックの話から始めて実際にメモリ上に作られるスタックフレームの話まで書いています。また、メモリより外の世界としてI/Oの話も扱います。CPUはI/Oを介して外界に繋がらなければ役立つ仕事はできません。エミュレータにin/out命令とキャラクタデバイスを実装し、実際にキーボード入力とディスプレイ出力を行えるようにしてみます。

最後の章では、実機でプログラムを実行する方法も説明しています。USBメモリのブートセクタに自作の機械語を書き込み、パソコンを起動させ、OSの力を借りずにプログラムを実行させます。BIOSの文字表示機能を使って、色付きの文字列を画面に表示させるのがゴールです。




この本はC言語の入門書を読み終わったくらいのレベルの人が読めることを目指して書いているため、C言語プログラミングで入門の次に知ると良さそうな事柄、例えばファイル分割の方法とか、printfで色付きの文字列を出力する方法なども扱っています。1章分のページをまるまる使って、アセンブリ言語の視点からポインタを学び直すので、C言語のポインタで躓いてしまった人にも何らかのひらめきを与えられる可能性があります。

また、本書を通してx86エミュレータというある程度の規模のソフトウェアを作りあげる経験を通して、読者のプログラミング能力を養おうという裏の目標もあったりします。手軽にx86の機械語を実行できる環境を作るという(ある意味)実用的なゴールを持ってプログラミングを行うことで、学習のための学習より効果の高いプログラミング練習になるでしょう。

お近くの書店で目についた際にチラ見していただければ幸いです。

最後に目次情報を載せておきます。

Chapter 1: C言語とアセンブリ言語

  • 1.1. C言語から機械語へ
  • 1.2. 機械語とアセンブリ言語
  • 1.3. 機械語に飛び込む
  • 1.4. アセンブリ言語を少し詳しく
  • 1.5. 基本のmov命令
  • 1.6. インクリメント専用のinc命令
  • 1.7. 16進数入門
  • 1.8. 2の補数入門

Chapter 2: ポインタとアセンブリ言語

  • 2.1. レジスタ
  • 2.2. メモリ
  • 2.3. 初めてのエミュレータ
  • 2.4. ポインタの復習
  • 2.5. ポインタに飛び込む
  • 2.6. 構造体とポインタ
  • 2.7. 不完全型とポインタ
  • 2.8. 関数ポインタ

Chapter 3: CPUがプログラムを実行する仕組み

  • 3.1. プログラムの配置
  • 3.2. エミュレータのorg対応
  • 3.3. プログラムの実行
  • 3.4. エミュレータのModR/M対応
  • 3.5. 無条件分岐命令
  • 3.6. call命令とスタック
  • 3.7. エミュレータのcall対応
  • 3.8. ローカル変数とスタック
  • 3.9. フラグレジスタと条件分岐命令
  • 3.10. エミュレータの条件分岐命令対応
  • 3.11. プログラムの繰り返し
  • 3.12. デバイスアクセス

Chapter 4: BIOSの仕組みと実機起動

  • 4.1. BIOS
  • 4.2. BIOSの実装
  • 4.3. 割り込み
  • 4.4. ブートセクタ
  • 4.5. PBRを見てみよう
  • 4.6. 実機で動かしてみよう

2015年7月17日金曜日

Lavie Direct HZ に Arch Linux をインストール

大まかな流れは Installation guide - ArchWiki に沿えばいいのですが、幾つかハマりポイントがあったのでメモを残しておきます。

起動メディアの準備

Lavie Direct HZ(以下 Lavie)には DVD ドライブなどは無いので USB 経由の何かで起動することになります。今回は USB メモリでやることにしました。

USB メモリへの書き込みは Silicon Linux さんの DD for Windows とか John Newbigin さんの dd for windows などを利用すれば簡単です。これらのツールは管理者権限で起動するのがポイントといえばポイントでしょうか。

インストーラの起動

工場出荷時の設定にも依るのでしょうが、僕が買ったマシンでは UEFI が USB 系のメディアより内蔵 SSD を優先して起動する設定になっていたので、 Lavie 起動画面で F2 を押して UEFI の設定画面に行き、起動優先度を変更しておきます。

さらに(少なくとも僕のマシンでは) UEFI のセキュアブートが有効になっているので、先ほど準備した USB メモリを挿して電源を入れても「Failed to Start loader」というエラーが出てインストーラが起動しません。セキュアブートを無効にしておきましょう。

※ Unified Extensible Firmware Interface - ArchWiki では loader.efi と vmlinuz.efi に対して Enroll Hash (ハッシュ値を登録)を実行して回避する手順が載ってますが、後々で別のエラー(Secure Boot Violation)が出ますので、セキュアブートを無効にしてしまうのが手っ取り早いでしょう。


フォントの調整

インストーラが起動して最初に思うのは、きっと「フォントちっさ!」だと思います^^;
Lavie は解像度が高すぎ、普通のフォントだと小さすぎるわけです。目が疲れてしまいますので、大きいフォントをインストールしましょう。My fonts are too tiny で紹介されている Terminus font を入れることにします。

まず、ワイヤレスネットワークの設定を済ませます。Installation guide の "Connect to the Internet" を参考に wifi-menu コマンドを使えば簡単に設定できます。

インターネットアクセスができるようになったら pacman のミラーリストで日本のミラーを一番上に持っていきます(ミラーの設定は必須ではないですが pacman の動作速度に大きな影響があります)。その後 pacman -Syy でパッケージリストを更新します。更新が完了したら pacman -S terminus-font でフォントをインストールしましょう。 /usr/share/kbd/consolefonts/ 以下に ter-xxx.psf.gz みたいなフォントファイルがインストールされるはずです。

最後にフォントを適用します。 setfont ter-128n (28 がサイズを表します。Terminus font の最高は 32 のようです。)でちょうどいい大きさのフォントになるはずです。128b とか 228n/b とか u28n/b みたいなフォントファイルもあるようですが、違いは分かりませんでした。

ブートローダの優先度設定

UEFI ブートをしたかったので GRUB を選びました。普通に GRUB をインストールし grub-mkconfig した後再起動しても Windows のブートローダが立ち上がってしまうので、 UEFI の設定画面(起動時に F2 を押すやつ)の Boot タブの "Hard Disk Drive BBS Priorities" から優先度を変えてやります。1st Boot として arch_grub を指定してあげれば OK です。

efibootmgr コマンドを使うとあたかも優先度を変更できそうなのですが、 Lavie の UEFI 実装と相性が悪いのか、再起動すると優先度設定が元に戻ってしまうようです。

タッチパッドが(時々)効かない

僕の場合はカーネルの起動オプションに i8042.reset を付け加えることで解決できました。/etc/default/grub の GRUB_CMDLINE_LINUX_DEFAULT に i8042.reset を加え、 sudo grub-mkconfig -o /boot/grub/grub.cfg とします。

以下、解決するまでのストーリー

タッチパッドが効くときと効かないときの xinput コマンドの出力を比べてみると、デバイスが検出できているかどうかの問題切り分けができます。僕の場合、この時点でデバイスが検出できてないことが分かっていました。

また、何度も再起動を繰り返す中で、タッチパッドが使えない時は必ず起動後の 1 文字目のキーボード入力が捨てられることも判明していました。ログイン画面でユーザ名を入力する際、 1 文字目が入力できないのです。したがって、キーボードコントローラ周りの初期化にミスってるのではないかと見当を付けて解決法を探しました。

解決に導いてくれたのは Touchpad not recognized on new Ultrabook という質問でした。この中の回答で i8042.nomux オプションを付けたら解決するかも、という記述があり試しました。結果としてこのオプションは僕の環境では効果はありませんでした。しかし i8042.nomux をキーワードに検索してみると What does the 'i8042.nomux=1' kernel option do during booting of Ubuntu? という質問に辿り着き、 i8042.reset の存在が分かりました。

数回再起動実験をしていますが、今のところすっかり直っている感じです。