debian

最近は、アンケートの事をアンケなんて言うみたいだけど、日本語乱れていませんかね。 国語審議会の面々が、しかめ面してるに違いない。

どうしてこんな忙しい世の中になっちゃんたんだろう? 上の例だと、アンケの後にちょっとだけ、 足せば済むと思うんだけど。それすら面倒なんですかね?

これもそれも、持ち歩き筆記用具兼世界探知機兼お財布兼お話端末が流行っているせいだな。 ガラケ、おっと旧式日本限定仕様携帯電話機が廃って、なでなでツールになってから、この傾向が 加速されてるように思えてならない。入力が面倒なんだな。だったら、補完機能を使うなり、マクロ で展開するなり、いろいろ手は有るだろうに。と、ここまで考えて、楽々スマホを使う人たちには 難しいか。

アンケートの事が出てきたので、アンケの結果を貼ります。

好きなアセンブラは何ですか?

これ、KOZOSの作者様が、カーネル探検隊の時に行ったものだそうです。母数が少ないのでバイアスが かかっているかも知れませんが、x86が好きが一番って本当? mipsとか6809とか、綺麗な石が好きってんだら、肯けますよ。

CISCとRISCとどっちが好きかは、RISC派が多いですね。CISCってほとんど、あの石しか無いと 思うんだけど、どうだろう?

ビット幅は、32Bitが半数か。RISCだと伸び伸びと32Bitがいいて事だな。ARMみたいにせせこましい のはお気に召さないとな。そう言えば、glibを開発してる大将も、ARMの変態性には付き合って らんねぇよとpatchを無視しちゃってましたな。

それで、glib開発プロジェクトがフォークして。。。debian様は、フォークした方に乗っかったとな。 たまには、debian様にも付き合ってみるか。

mips de debian

どうせやるならRISCでってのがお約束。CISCは願い下げですって威勢の良い事を言っても、多種多様な 石に対応したLinuxが出てるんかい? 調べてみたら、 DebianをMIPS on QEMU環境で動かす なんていう奇特な方がおられた。その元締めが公開してる蔵 が有りました。

母艦はdebianと親和性が高い、ArchLinuxを使う事にします。 最初、例に倣ってLennyをDLして起動してみたんだけど、お目当てのgccとかが無かったので、 squeezeの方を使いました。Debianは、バージョンを愛称で呼んでるけど、そんなのDebian Loveな 人にしか通じないよ。squeezeの方は、現世代。lennyは旧世代なのね。

[    0.000000] Linux version 2.6.32-5-4kc-malta (Debian 2.6.32-30) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 Wed Jan 12 06:13:27 UTC 2011
[    0.000000]
[    0.000000] LINUX started...
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU revision is: 00019300 (MIPS 24Kc)
[    0.000000] FPU revision is: 00000000
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 00001000 @ 00000000 (reserved)
[    0.000000]  memory: 000ef000 @ 00001000 (ROM data)
[    0.000000]  memory: 005af000 @ 000f0000 (reserved)
[    0.000000]  memory: 07961000 @ 0069f000 (usable)
[    0.000000] Wasting 54240 bytes for tracking 1695 unused pages
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone PFN ranges:
[    0.000000]   DMA      0x00000000 -> 0x00001000
[    0.000000]   Normal   0x00001000 -> 0x00008000
[    0.000000] Movable zone start PFN for each node
[    0.000000] early_node_map[1] active PFN ranges
[    0.000000]     0: 0x00000000 -> 0x00008000
[    0.000000] On node 0 totalpages: 32768
[    0.000000] free_area_init_node: node 0, pgdat 805ecf10, node_mem_map 8100000
0
[    0.000000]   DMA zone: 32 pages used for memmap
[    0.000000]   DMA zone: 0 pages reserved
[    0.000000]   DMA zone: 4064 pages, LIFO batch:0
[    0.000000]   Normal zone: 224 pages used for memmap
[    0.000000]   Normal zone: 28448 pages, LIFO batch:7
[    0.000000] CPU frequency 199.81 MHz

dmesgから面白そうな所を抜き出してみた。200MHzでのんびりと動きますですって。

そんじゃ、apt-get update; apt-get dist-upgrade してから、gcc gdb make あたりを入れて やる。のんびり、のんびりと時間は過ぎて行きます。

そして試運転は、例のSimpleって言うSchemeですね。8月初旬バージョンでは、下記の ような規模だった。

sakae@debian-mipsel:~/Simple$ wc -l *.[ch]
   535 cell.c
  1576 compute.c
  3681 function.c
   668 list.c
  2569 main.c
   356 simp.h
  9385 total

コンパイルに要する時間を計ってみる。

sakae@debian-mipsel:~/Simple$ time make
  :
real    9m21.768s
user    9m11.390s
sys     0m6.696s

のんびり、のんびりとコンパイルされて、無事に動きました。目出度し目出度しと思って、 shutdown -h now したら、rebootしちゃったよ。これって、mipsストーカー?

逃げ出しましょ。そして、変態モード突入だ。

arm de debian

QEMUでARM環境を手にいれる を参考にします。但し、使うのは例によってsqueeze版ですね。

何も入っていないので、コンパイル環境を整えます。おいら的には、コンパイラーが入っていない unixなんてunixとは認定されませんってのが有るんだけど、Windows代替用OSだからなあ、しょうが ないか。 本当に腹が立ったのは、SunOS止めてSolarisにしちゃった亡社。コンパイラー欲しかったら、買え ってすげない態度に怒り心頭でしたね。後にコンパニオンCDでお茶を濁すなよ。そんな事だから、 ボラクルへ身売りしちゃうんだよ。プンプン。

怒りを静めて、コンパイルしてみました。

sakae@debian-armel:~/Simple$ time make
gcc  -g -c main.c
gcc  -g -c cell.c
gcc -g -c list.c
gcc -g -c function.c
gcc -g -c compute.c
gcc  -g main.o cell.o list.o function.o compute.o -o simp -lm

real    1m4.247s
user    0m57.030s
sys     0m5.540s

mipsに比べて、随分早いな。そう言えば、おいらのアカウントを作る時、useradd -m -d /home/sakae sakae したんだけど、 これだとlogin-shellが、/bin/shなのね。loginしてからプロンプトが出てくるまで早い。所が、chsh して、/bin/bashに切り替えた途端、loginまで非常に時間がかるようになった。rootはデフォで、/bin/bashが 使われているけど、これってどうよ。ちゃんとstatic-linkになってるんかいな? どうも、 代替用OSは(本物同様) 信用ならん。

まあまあ落ち着いて、コンパイル結果を確かめてみましょ。

sakae@debian-armel:~/Simple$ ./simp
educational Scheme compiler Simple Ver0.31.3 (written by Kenichi.Sasagawa)
Exception: incorrect argument count in call ((null))
Exception: incorrect argument count in call (map)
*** glibc detected *** ./simp: double free or corruption (!prev): 0x00657b38 ***
Aborted

しょうがないので、gdbから実行してbt取ってみたら、libcの中でうろいろしてた。どこをほっつき 歩いているかと思ったら、

Dump of assembler code for function raise:
0x4010ccc8 <raise+0>:   push    {r4, r5, r7, lr}
0x4010cccc <raise+4>:   mov     r4, r0
0x4010ccd0 <raise+8>:   bl      0x400f7990
0x4010ccd4 <raise+12>:  ldr     r3, [r0, #-1112]        ; 0x458
0x4010ccd8 <raise+16>:  mov     r2, r0
0x4010ccdc <raise+20>:  cmp     r3, #0
0x4010cce0 <raise+24>:  ldr     r0, [r0, #-1108]        ; 0x454
0x4010cce4 <raise+28>:  bne     0x4010cd18 <raise+80>
0x4010cce8 <raise+32>:  mov     r7, #224        ; 0xe0
0x4010ccec <raise+36>:  svc     0x00000000
0x4010ccf0 <raise+40>:  mov     r3, r0
0x4010ccf4 <raise+44>:  str     r0, [r2, #-1112]        ; 0x458
   :

svc って、ひょっとしてシステムコール? ちゃんと一番下の階層まで着ましたねぇ。ここで 追いかけを始めるとストーカーになっちゃうんで、華麗にスルーします。諦めが肝心って事も あるんよ。それが、大人の対応ってもんです。

中には、諦めないで頑張っておられる人も居ました。 こちらの方は頑張って、QEMU-FM3 をMacで動かす んですって。それもこれも、CQ出版社が日本の電子業界を牽引してるからです。 気前よく、Interfaceダウンロードのページを 公開してるCQ出版社に、拍手!

bootはどうなってるん?

armelなdebian様を起動するスクリプトは次のようにしている。

[sakae@archbang armel]$ cat boot
#!/bin/sh

qemu-system-arm -M versatilepb \
 -kernel vmlinuz-2.6.32-5-versatile \
 -initrd initrd.img-2.6.32-5-versatile \
 -hda debian_squeeze_armel_standard.qcow2 \
 -append "root=/dev/sda1 console=ttyAMA0" \
 -nographic \
 -redir tcp:2222::22

そもそもinitrdって何よ? いろんな引数が有って、QEMUは随分とLinuxにバイアスされてるな。 カーネルに渡す引数に、consoleを追加しておくと、起動までのメッセージが画面にずらずらと 表示される。(mips版の方は、途中まで表示されて、随分経ってから、いきなりloginプロンプトが 出て来る。これもそれも、GUIで使っていないからだと思うけど。)

で、このブートメッセージは、どんどんと流れて行ってしまうので、追うのが大変。ログに 落としましょ。

[sakae@archbang armel]$ ./boot >LOG 2>&1

こうすると、くまなくLOGファイルに記録されるけど、ログイン出来なくなっちゃう。そこで、sshログインですね。 勿論、こういう無謀?な事をやる前に、sshをインストールして起動しとく事。

このLOGはdmesgで表示されるメッセージより詳細に載ってるんで、楽しみがブーストされます。 以下、LOGから面白そうな所を拾っていきます。

oss: Could not initialize DAC
oss: Failed to open `/dev/dsp'
oss: Reason: No such file or directory

これって本物のハードには、オーディオの石が載ってるんでしょうな。

[    0.000000] Linux version 2.6.32-5-versatile (Debian 2.6.32-30) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 Wed Jan 12 23:05:11 UTC 2011
[    0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] Machine: ARM-Versatile PB

石の素性。ukな人がARMなdebianを開発してるって事は、ひょっとしてbenさんは、ARMな関係者? と、イギリスの探偵君でなくても想像出来るぞ。(BSで現代版のシャーロックホームズ君とかポアロ君が 活躍してましたなぁ)

Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... 
Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... done.
[   11.931712] kjournald starting.  Commit interval 5 seconds
[   11.934984] EXT3-fs: mounted filesystem with ordered data mode.
Begin: Running /scripts/local-bottom ... done.
done.
Begin: Running /scripts/init-bottom ... done.
^@^@
INIT: ^@version 2.88 booting^@
^@Using makefile-style concurrent boot in runlevel S.
  :
INIT: ^@Entering runlevel: 2^@

^@Using makefile-style concurrent boot in runlevel 2.
Starting enhanced syslogd: rsyslogd.
Starting OpenBSD Secure Shell server: sshd
[   42.078511] ipv6: Unknown symbol sock_queue_err_skb
Debian GNU/Linux 6.0 debian-armel ttyAMA0

注目は、INITが走る前に実行してる、/scriptsの中にあるスクリプト類。これって何や? DISKの 中にはそんなの無いんですけど。。後で調べてみるぞっていう事で、todoをpushしときます。

INITが走りだすと、ランレベルをSで実行してから2に移行するんだな。その中で、いろいろなものを 起動してるとな。その置き場所は、/etc/rc2.dの中か。

マシンを落とす時は、

INIT: Switching to runlevel: 0

INIT: Sending processes the TERM signal

^@Using makefile-style concurrent boot in runlevel 0.
Stopping MTA:.
  :
Cleaning up ifupdown....
Deactivating swap...done.
Will now halt.
[ 1165.654012] System halted.
qemu: terminating on signal 15 from pid 466

マシンを落とす時は、runlebel0を告げられて、rc0.dの中を順番に(stopオプションを付けて)実行 実行してくんだな。システムが止まっても、自動的にパワーオフにはならないので、最後は、qemu を殺してあげる。

この時のuptimeは、ARM時間によれば、1165秒だったとな。ARMの中と外では、時間の進み方が 違うのかなあ? だとすると、アインシュタインの特殊相対性理論が破綻して、えらい事になるぞ。 CERNやフェルミ研究所の偉い人、このあたりの解説を宜しく。

initrdって何や?

先ほどのtodoをpopします。スクリプトなんてのは無かったぞ。/bootの中にも! それに、qemuの引数に指定してる謎のファイル initrd.imgも有るしね。

sakae@debian-armel:~$ ls -l /boot
total 4524
-rw-r--r-- 1 root root   69664 May  7 01:50 config-2.6.32-5-versatile
lrwxrwxrwx 1 root root      29 Feb 28  2011 initrd.img -> initrd.img-2.6.32-5-versatile
-rw-r--r-- 1 root root 2352996 Aug 28 04:41 initrd.img-2.6.32-5-versatile
-rw-r--r-- 1 root root  936400 May  7 01:50 System.map-2.6.32-5-versatile
lrwxrwxrwx 1 root root      26 Feb 28  2011 vmlinuz -> vmlinuz-2.6.32-5-versatile
-rw-r--r-- 1 root root 1246756 May  7 01:49 vmlinuz-2.6.32-5-versatile

しょうがないから、正体を探ってみる。

[sakae@archbang armel]$ file initrd.img-2.6.32-5-versatile
initrd.img-2.6.32-5-versatile: gzip compressed data, from Unix, last modified: Mon Feb 28 15:19:20 2011
[sakae@archbang armel]$ file vmlinuz-2.6.32-5-versatile
vmlinuz-2.6.32-5-versatile: Linux kernel ARM boot executable zImage (little-endian)

両方共、圧縮されてるんか。そなら、展開するか、って、ユニマガの(Liniux | FreeBSD)の ブートプロセスを見るの解説者風、語り口になってます。

[sakae@archbang armel]$ zcat initrd.img-2.6.32-5-versatile > t/initrd
[sakae@archbang t]$ file initrd
initrd: ASCII cpio archive (SVR4 with no CRC)
[sakae@archbang t]$ cpio -id < initrd
9964 blocks
[sakae@archbang t]$ ls -l
total 5016
drwxr-xr-x 2 sakae users    4096 Aug 30 12:40 bin
drwxr-xr-x 3 sakae users    4096 Aug 30 12:40 conf
drwxr-xr-x 4 sakae users    4096 Aug 30 12:40 etc
-rwxr-xr-x 1 sakae users    5955 Aug 30 12:40 init
-rw-r--r-- 1 sakae users 5101568 Aug 30 11:22 initrd
drwxr-xr-x 4 sakae users    4096 Aug 30 12:40 lib
drwxr-xr-x 2 sakae users    4096 Aug 30 12:40 sbin
drwxr-xr-x 5 sakae users    4096 Aug 30 12:40 scripts

出てきましたねぇ。scripts この中には多数のスクリプトファイルが置いてあった。ついでに、 initもシェルスクリプトだ。これが親分なのね。読んでみると面白い。

詳しい事は、 bootの仕組みあたりを参照かな。 そうそう、vmlinuzの方は、展開する方法が無い(しかるべきコンテキストで自己解凍するように、 秘密めかして作ってあるようです。リナス君、君は一体何を考えんとるかね)

おまけでrubyで一行野郎

先週の枕でちょっと書いた、16進数4文字単語を抽出するやつ。一行野郎が思った通りに 動かなかったけど、使い方を間違えてた。(manは読むもんだと改めて認識)

[sakae@archbang ~]$ ruby -ne 'puts $_ if $_ =~ /^[a-f]{4}$/' /usr/share/dict/cracklib-small
abbe
abed
babe
bade
bead
beef
cafe
cede
dada
dade
dead
deaf
deed
face
fade
feed

上のやつでも十分用が足りるんだけど(それにしてもArchLinuxの英単はすごい名前が付いてるな。 日本人なら、赤単とか付けるべし)、一行野郎に if は、いかがなものかと思ったり、思わなかったり しませんか。Lisp屋さんならそこで、and の登場ですよ。中置法が気にいらないはrubyだから しょうがないと諦める事として、

[sakae@archbang ~]$ ruby -ne '$_ =~ /^[a-f]{4}$/ and puts $_' /usr/share/dict/cracklib-small

この方が、目線を左から右へ移動させるだけなんで、コマンドラインには適しているかと。。でも if を 使った方は冗長に書いたけど、if 正規表現 だけでいいのね。そうすると、やっぱり if に軍配が 上がるかな。

久しぶりに ruby man した訳だけど、面白いオプション発見。ifとandはどう違う? andがマクロで (rubyの場合はマクロって禁句でDSLって言うんだな)、ifに展開されるとかかなあ?

[sakae@archbang ~]$ ruby --dump insns -e 'puts $_ if $_ =~ /^[a-f]{4}$/'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
0000 trace            1                                               (   1)
0002 getglobal        $_
0004 putobject        /^[a-f]{4}$/
0006 opt_regexpmatch2
0007 branchunless     20
0009 putself
0010 getglobal        $_
0012 send             :puts, 1, nil, 8, <ic:0>
0018 leave
0019 pop
0020 putnil
0021 leave
[sakae@archbang ~]$ ruby --dump insns -e '$_ =~ /^[a-f]{4}$/ and puts $_'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
0000 trace            1                                               (   1)
0002 getglobal        $_
0004 putobject        /^[a-f]{4}$/
0006 opt_regexpmatch2
0007 dup
0008 branchunless     20
0010 pop
0011 putself
0012 getglobal        $_
0014 send             :puts, 1, nil, 8, <ic:0>
0020 leave

この場合は、andの方が素直だなあ。ifの方は、使いもしない、nilを返しているね。

あの人の頭の中はどうなってる?

[sakae@archbang ~]$ ruby --dump parsetree -e 'puts $_ if $_ =~ /^[a-f]{4}$/'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_IF (line: 1)
#     +- nd_cond:
#     |   @ NODE_MATCH3 (line: 1)
#     |   +- nd_recv:
#     |   |   @ NODE_LIT (line: 1)
#     |   |   +- nd_lit: /^[a-f]{4}$/
#     |   +- nd_value:
#     |       @ NODE_GVAR (line: 1)
#     |       +- nd_entry: :$_
#     +- nd_body:
#     |   @ NODE_FCALL (line: 1)
#     |   +- nd_mid: :puts
#     |   +- nd_args:
#     |       @ NODE_ARRAY (line: 1)
#     |       +- nd_alen: 1
#     |       +- nd_head:
#     |       |   @ NODE_GVAR (line: 1)
#     |       |   +- nd_entry: :$_
#     |       +- nd_next:
#     |           (null node)
#     +- nd_else:
#         (null node)
[sakae@archbang ~]$ ruby --dump parsetree -e '$_ =~ /^[a-f]{4}$/ and puts $_' 
  :
# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_AND (line: 1)
#     +- nd_1st:
#     |   @ NODE_MATCH3 (line: 1)
#     |   +- nd_recv:
#     |   |   @ NODE_LIT (line: 1)
#     |   |   +- nd_lit: /^[a-f]{4}$/
#     |   +- nd_value:
#     |       @ NODE_GVAR (line: 1)
#     |       +- nd_entry: :$_
#     +- nd_2nd:
#         @ NODE_FCALL (line: 1)
#         +- nd_mid: :puts
#         +- nd_args:
#             @ NODE_ARRAY (line: 1)
#             +- nd_alen: 1
#             +- nd_head:
#             |   @ NODE_GVAR (line: 1)
#             |   +- nd_entry: :$_
#             +- nd_next:
#                 (null node)

ふーん、これだけじゃよく分からんな。インラインで短いスクリプトを与える代わりに、 試験問題が大量に詰まったスクリプトファイルで、精密に分析かなあ。 それとも、manした時に出てきた

     -y
     --yydebug      DO NOT USE.

                    Turns on compiler debug mode.  Ruby will print a bunch of
                    internal state messages during compiling scripts.  You
                    don't have to specify this switch, unless you are going to
                    debug the Ruby interpreter.

使うなってやつを使って

sakae@ubuntu:~$ ruby -ye 'puts $_ if /^[a-f]{4}$/'
Starting parse
Entering state 0
Reducing stack by rule 1 (line 782):
-> $$ = nterm $@1 ()
Stack now 0
Entering state 2
Reading a token: Next token is token tIDENTIFIER ()
Shifting token tIDENTIFIER ()
Entering state 35
Reading a token: Next token is token tGVAR ()
Reducing stack by rule 547 (line 4816):
   $1 = token tIDENTIFIER ()
-> $$ = nterm operation ()
Stack now 0 2
  :
-> $$ = nterm program ()
Stack now 0
Entering state 1
Now at end of input.
Shifting token $end ()
Entering state 3
Stack now 0 1 3
Cleanup: popping token $end ()
Cleanup: popping nterm program ()

で、問題の解き方を観察する? ちゃんと勉強すれば、筑波とか東大に入れるかも?