dtrace機能を有効にしたNetBSDインストールCDを作成してみた
dtrace機能を有効にしたNetBSDインストールCDを作成してみた
NetBSDのdtrace機能を試してみようと思い立ち、@akachochinさんのNetBSD dtrace格闘記その2を元にdtrace機能を有効にしたインストールCDの作成手順をまとめてみました。
インストールCD作成準備
@akachochinさんのblogでは、インストール済みのNetBSD環境に直接dtraceまわりのカーネルモジュールをインストールしています。私の環境ではdtraceを有効にしたNetBSDのインストールCDを作成したいため、まずはインストールCD作成用のNetBSD環境を準備します。
ソースコードを展開する
NetBSD-6.1.3-i386を仮想マシンにインストールした後、ソースコードを展開します。
# mount /dev/cd0a /cdrom # cd /cdrom/source/sets/ # ls -l *.tgz -r--r--r-- 1 root wheel 43069713 Jan 19 20:15 gnusrc.tgz -r--r--r-- 1 root wheel 7661899 Jan 19 20:16 sharesrc.tgz -r--r--r-- 1 root wheel 203542266 Jan 19 20:14 src.tgz -r--r--r-- 1 root wheel 40189162 Jan 19 20:15 syssrc.tgz -r--r--r-- 1 root wheel 158393066 Jan 19 20:18 xsrc.tgz
ソースコードは/usr/src以下に展開します。
# for i in *.tgz; do tar zxvf $i -C /; done
カーネルコンフィグを修正してdtrace機能を有効化する
dtrace機能を有効にするためのカーネルコンフィグを追加します。INSECURE,KDTRACE_HOOKS,MODULARを有効にする必要がありますが、GENERICコンフィグではINSECURE,MODULARは既に有効になっていたため、KDTRACE_HOOKSのみ追加します。
# cd /usr/src/sys/ # diff -u arch/i386/conf/GENERIC.orig arch/i386/conf/GENERIC --- arch/i386/conf/GENERIC.orig 2012-08-16 00:33:00.000000000 +0900 +++ arch/i386/conf/GENERIC 2014-04-13 02:23:38.000000000 +0900 @@ -74,6 +74,7 @@ # Standard system options options INSECURE # disable kernel security levels - X needs this +options KDTRACE_HOOKS options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT options NTP # NTP phase/frequency locked loop
build.shを実行する
build.shを使用して一通りのビルドを行います。ビルドは時間がかかるので、以下のスクリプトを作成し、バッチ処理的にビルドを行うようにしました。
上記のスクリプトをMac mini(2.4GHz Intel Core 2 Duo,メモリ 8GB)のVirtualBox上のNetBSDで走らせたところ、全てのビルドが完了するまで15時間程度かかりました。
ビルドが完了すると、以下の場所にdtrace機能が有効になったインストールCDが生成されます。
/usr/obj/distrib/i386/cdroms/installcd/NetBSD-6.1.3-i386.iso
OSインストール後のdtrace機能を利用するための設定投入
インストールCDが作成できたので、このCDを使用してNetBSDを再度インストールします。インストール後、dtrace用にデバイスファイルを作成します(OSインストール後に一度行うだけで良い)。
# mkdir /dev/dtrace # mknod /dev/dtrace/dtrace c dtrace 0
そして、OS起動時にdtraceに必要なカーネルモジュールをロードするよう設定します。もっとスマートな方法があると思うのですが、今回は/etc/rc.localに以下の処理を追加しました。
_MODULE=" solaris dtrace sdt fbt " for i in ${_MODULE} do echo "modload ${i}" modload ${i} done
OSを再起動するとdtrace機能が利用可能になっています。
# dtrace -l | wc -l 45326
dtrace機能を試してみる
NetBSDでdtraceが利用できるようになったので、例としてgetpid()システムコールをフックさせてみます。
"getpid"というキーワードにマッチする関数は、sys_getpid(),sys_getpid_with_ppid()の2つがあるようです。
# dtrace -l | grep getpid 21001 fbt netbsd sys_getpid entry 21002 fbt netbsd sys_getpid return 21003 fbt netbsd sys_getpid_with_ppid entry 21004 fbt netbsd sys_getpid_with_ppid return
どちらがgetpid()システムコールの実体か分からないので、"getpid"でマッチするようにしてみます。dtrace -nを実行すると、その端末内で出力待ちの状態になります。
# dtrace -n fbt:netbsd:*getpid*:entry dtrace: description 'fbt:netbsd:*getpid*:entry' matched 2 probes
別の端末にて、getpid()を実行するサンプルプログラムを用意します。
# cat _getpid.c #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { printf("%d\n", getpid()); return 0; } # gcc -Wall -Werror -g -o _getpid _getpid.c
サンプルプログラムを実行すると、dtraceを実行している端末に以下が出力されます。
# dtrace -n fbt:netbsd:*getpid*:entry dtrace: description 'fbt:netbsd:*getpid*:entry' matched 2 probes CPU ID FUNCTION:NAME 0 21003 sys_getpid_with_ppid:entry 0 21003 sys_getpid_with_ppid:entry
getpid()の実体はsys_getpid_with_ppid()のようです。プロセスの生成時にもsys_getpid_with_ppid()は呼ばれるようで、出力が2回になっています。
# cat -n /usr/src/sys/kern/kern_prot.c 81 /* ARGSUSED */ 82 int 83 sys_getpid_with_ppid(struct lwp *l, const void *v, register_t *retval) 84 { 85 struct proc *p = l->l_proc; 86 87 retval[0] = p->p_pid; 88 retval[1] = p->p_ppid; 89 return (0); 90 }
まとめ
NetBSDでdtrace機能を試してみました。デフォルトインストールではdtrace機能が有効で無いため、カーネルとカーネルモジュールの構築が必要です。インストールCDが欲しかったので、備忘録を兼ねた一通りのビルド手順についてもまとめてみました。
ポケットミクでテキスト読み上げ
ポケットミクでテキスト読み上げ
学研から発売された「歌うキーボード ポケットミク」を動かしてみました。
カーボンキーボードで演奏すると、初音ミクが「どーれーみー」という感じで歌ってくれます。また、MIDIデバイスとして利用でき、例えばNetBSDでは以下のdmesgが得られます(NetBSD-6.1-i386の場合です)。
Apr 29 07:12:32 hayase /netbsd: uaudio0 at uhub3 port 3 configuration 1 interface 0
Apr 29 07:12:32 hayase /netbsd: uaudio0: NSX-39 NSX-39, rev 2.00/1.00, addr 2
Apr 29 07:12:32 hayase /netbsd: uaudio0: audio descriptors make no sense, error=4
Apr 29 07:12:32 hayase /netbsd: umidi0 at uhub3 port 3 configuration 1 interface 1
Apr 29 07:12:32 hayase /netbsd: umidi0: NSX-39 NSX-39, rev 2.00/1.00, addr 2
Apr 29 07:12:32 hayase /netbsd: umidi0: (genuine USB-MIDI)
Apr 29 07:12:32 hayase /netbsd: umidi0: out=1, in=1
Apr 29 07:12:32 hayase /netbsd: midi1 at umidi0: <0 >0 on umidi0
すばらしいことに、GitHub上にはRuby,Python等のスクリプトからポケットミクを操作するためのライブラリが有志によって公開されており、Rubyからポケットミクを操作できるpoket_mikuがあります。
pocket_mikuのインストール
私の環境では、以下の手順でpocket_mikuをインストールしました。
- Gemfileを作成する
以下の内容でGemfileを作成します。
source :rubygems gem 'pocket_miku', :git => "git://github.com/toshia/pocket_miku.git"
- gemでインストールする
$ sudo gem193 install pocket_miku
- 簡単なサンプルを試す
以下のサンプルを実行すると、初音ミクが「ふぁー ぼー」としゃべります。
#!/usr/bin/env ruby193 # -*- coding: utf-8 -*- require 'pocket_miku' PocketMiku.sing '/dev/rmidi1' do tempo 240 ふぁ 75; ぼ 82; end
ポケットミクでテキストを読み上げてみる
さて、無事にスクリプトから初音ミクにおしゃべりさせることができたワケですが、もう一歩進めて、今度はテキストを読み上げさせてみます。
以下のように、初音ミクにしゃべらせたい音をスクリプトから指定するだけでOKなのですが、「日本語」→「にほんご」のように、平仮名に直して指定する必要があります。
ふぁ 75; ぼ 82;
ここはサクっとChasenを使ってテキストを平仮名に直すという方法を試してみました。
Chasenによる形態素解析では、以下のような出力が得られます。読みの第一候補(第二カラム)を使うとうまく行きそうです。 (実はこのカラムの名称を知らず、Chasenマニュアルを読む羽目に...)
$ chasen
今日は良い天気です
今日 キョウ 今日 名詞-副詞可能
は ハ は 助詞-係助詞
良い ヨイ 良い 形容詞-自立 形容詞・アウオ段 基本形
天気 テンキ 天気 名詞-一般
です デス です 助動詞 特殊・デス 基本形
EOS
スクリプトは以下においてあります。
以下の手順でスクリプトを実行します(現状「!」とかの記号が入ったテキストだとエラーがでます...)。
$ echo 今日は良い天気です | chasen > data.txt
$ ./miksay.rb data.txt
テキストを読み上げたものの...
ポケットミクによるテキスト読み上げまで行えたのですが、いざ発声を聞いてみると、あまりよく聞き取れません。 しばらく聞いていて気がついたのですが、発声の「間」を調節しないと聞き取りにくいようです。
「キョウハ ヨイ テンキデス」という発声だと良いのですが、「キョウハヨイテンキデス」と一気に読み上げると、思っている以上に単語の区切りが分かりにくいです。日々会話する時にはほとんど意識しないのですが、この「間」は重要なのですね。
まとめ
スクリプトからポケットミクをしゃべらせてみました。形態素解析ツールを活用することでうまいこと仮名の切り出しが行えました。テキスト読み上げについては、発声の「間」などの考慮が必要そうで、まだまだ改良の余地ありです。
追記
肝心なことを忘れていました。5月6日に「ポケットミクちゃんに何かいろいろさせる会(その1)」という会を開催する予定です。ご興味のある方はぜひご参加ください。
「悪循環画像ジェネレータ」を作ってみた
悪循環画像とは
昨日くらいから、Twitter上で「悪循環コラ画像」というものが流行っているようです。元々はみやぎ県政だより(2010年12月号)http://www.pref.miyagi.jp/kohou/kenseidayori/backnumber/201012/special/special01.htmの薬物乱用防止の啓蒙記事にある、薬物依存の悪循環を示すイメージ図がオリジナルなのですが、妙に汎用性(?)があるのか、様々なジャンルでの悪循環コラが作られる状態になっています。
そこで悪循環コラ作成の一助になればと思い、「悪循環画像ジェネレータ」を作成してみました。ブラウザ上で文言を入力することで悪循環コラが作れるというものです。
悪循環画像ジェネレータ
URLは以下になります(2017/02/12追記:Bitbucketだと404 Requestが返されてしまうのでGitHub Pagesに引っ越しました)。
- http://furandon-pig.github.io/fpig_sample/hobby/bad_spiral/
http://furandon_pig.bitbucket.org/hobby/bad_spiral/
入力欄に文言を入力すると、オリジナル画像をテンプレ化(吹き出しの文字を消したもの)した画像に文言が反映されるという動作になっています。
(それしか機能がない……)
単に入力された文言をHTML5 CanvasのfillText()で描画するだけのはずだったのですが、<br>で改行できるようにしたところ、予想よりもちょっと複雑な処理になってしまいました。
というわけで、文言の中に<br>を入れると、改行文字として扱われ、かつ、配置も(ある程度)よきにはからってくれる動作になっています。
悪循環コラを作ってみる
簡単なサンプルとして、のんのんびよりの悪循環コラを作ってみました。
以下のような感じになります。
このツールでさらに悪循環コラが増えてくれればと思います。
その他
このアプリケーションはTwitter Bootstrapを利用したのですが、あまり活用できていません。また、バージョンが上がったのか、デザインやレイアウトルールが以前(1年くらい前)と変わっているようでした。
アセンブラ短歌を詠みつつブログを始めてみた
あけましておめでとうございます。
2014年の幕開けにあわせて、人もすなる日記といふものを始めようと思いたちました。
最初の日記は新年らしく(?)アセンブラ短歌を詠んでみることにしました。
アセンブリ短歌とは、http://kozos.jp/asm-tanka/で紹介されているように、機械語命令がちょうど五・七・五・七・七の並びにおさまるようにしたプログラムのことであります。
さっそく九九の表を出力するアセンブラ短歌を読んでみます。環境はNetBSD-6.1-i386です。
(数値を出力したかったのですが、ASCII文字にマッピングした文字を出力しています...)
コメントの5,7,5...の部分が五・七・五の切れ目になっており、このmain関数はアセンブラ短歌が2首入っています。
.globl main
main:
mov $0x01, %eax # 5
xloop: mov $0x01, %ebx
yloop: push %eax
nop # 7
imul %ebx
add $0x1f, %eax # 5
call my_putchar
mov $0x20, %al # 7
call my_putchar
pop %eax
inc %ebx # 7
cmp $0x0a, %ebx
jnz yloop # 5
ybreak: inc %eax
cmp $0x0a, %al
jz xbreak
push %eax
nop # 7
mov $0xa, %eax # 5
call my_putchar
pop %eax
nop # 7
jmp xloop
xbreak: nop
nop
nop
nop
ret # 7
.globl my_putchar
my_putchar:
sub $0x10, %esp
mov %eax,(%esp)
mov %esp,%eax
movl $0x1, 0xc(%esp)
movl %eax, 0x8(%esp)
movl $0x1, 0x4(%esp)
mov $0x4, %ax
int $0x80
add $0x10, %esp
ret
コンパイルと実行結果は以下のようになります。
$ gcc -Wall -Werror -g kuku.s
$ ./a.out
! " # $ % & ' (
! # % ' ) + - / 1
" % ( + . 1 4 7 :
# ' + / 3 7 ; ? C
$ ) . 3 8 = B G L
% + 1 7 = C I O U
& - 4 ; B I P W ^
' / 7 ? G O W _ g
( 1 : C L U ^ g p
1首目の短歌を逆アセンブルして見てみます。五・七・五・七・七のリズムで機械語命令を区切ることができます。
$ objdump -d a.out | grep -A20 '<main>:'
080486a0 <main>:
80486a0: b8 01 00 00 00 mov $0x1,%eax
080486a5 <xloop>:
80486a5: bb 01 00 00 00 mov $0x1,%ebx
080486aa <yloop>:
80486aa: 50 push %eax
80486ab: 90 nop
80486ac: f7 eb imul %ebx
80486ae: 83 c0 1f add $0x1f,%eax
80486b1: e8 28 00 00 00 call 80486de <my_putchar>
80486b6: b0 20 mov $0x20,%al
80486b8: e8 21 00 00 00 call 80486de <my_putchar>
80486bd: 58 pop %eax
80486be: 43 inc %ebx
80486bf: 83 fb 0a cmp $0xa,%ebx
80486c2: 75 e6 jne 80486aa <yloop>
080486c4 <ybreak>:
80486c4: 40 inc %eax
アセンブラ短歌の詠み方としては、以下のような流れになります。
x86アーキテクチャでは、意外と最初から五・七・五...になっていることも多いです。
機械語命令がうまいこと五・七・五...にならない場合、以下の方法で命令数を調整します。
これ他にも機械語命令数の調整方法はあるかと思います。筆者は上記の3パターンで何とかアセンブラ短歌を詠めています。
皆様も新年はアセンブラ短歌で(プログラムの)書き初めをしてみてはいかがでしょうか。
【1/4追記】環境の記述が抜けていたので追記しました。