dmesg に出る、
[123035.658852] ACPI Error (psargs-0359): [\_TZ_.TZ01] Namespace lookup failure, AE_NOT_FOUND [123035.658875] ACPI Error (psparse-0537): Method parse/execution failed [\_SB_.PCI0.LPC0.EC0_._Q11] (Node ffff88015d834a00), AE_NOT_FOUND
というメッセージを調べたのだが、あまりよくわからない。
% sudo acpidump -b -t DSDT -o DSDT.aml % iasl -d DSDT.aml
とすると、ACPI の処理の指示が DSDT.dsl として読めて、それのどこかに問題があるのではないかと疑っているが定かでない。
Ubuntu で驚いたのは、/etc/hostname を書き換えると、それに伴って自動的に hostname が変化し、さらに /etc/hosts も書き換わることである。
/etc/hostname が foo のときに
% hostname foo % grep localhost.localdomain /etc/hosts 127.0.0.1 foo localhost.localdomain localhost
となっていたとして、/etc/hostname を bar として書き込むと、信じがたいことに、自動的に、
% hostname bar % grep localhost.localdomain /etc/hosts 127.0.0.1 bar localhost.localdomain localhost
となる。
いったいどうやっているんだ?
/var/log/daemon.log をみると、NetworkManager なるものの仕業らしい。
inotify で監視しているようだ。
inotify はどのくらい使われているか?
% sudo lsof 2>/dev/null|grep inotify|sort NetworkMa 934 root 10r DIR 0,10 0 1 inotify NetworkMa 934 root 12r DIR 0,10 0 1 inotify avahi-dae 920 avahi 13r DIR 0,10 0 1 inotify compiz.re 3060 akr 15r DIR 0,10 0 1 inotify dbus-daem 853 messagebus 5r DIR 0,10 0 1 inotify dbus-daem 2828 akr 7r DIR 0,10 0 1 inotify firefox 3795 akr 39r DIR 0,10 0 1 inotify firefox 4086 akr 48r DIR 0,10 0 1 inotify firefox 4086 akr 80r DIR 0,10 0 1 inotify gdm-binar 894 root 5r DIR 0,10 0 1 inotify gdu-notif 3129 akr 7w DIR 0,10 0 1 inotify gnome-key 2746 akr 6r DIR 0,10 0 1 inotify gnome-pan 3061 akr 20u DIR 0,10 0 1 inotify gnome-set 2902 akr 20r DIR 0,10 0 1 inotify gnome-ter 3764 akr 15r DIR 0,10 0 1 inotify gnome-ter 3764 akr 20r DIR 0,10 0 1 inotify gtk-windo 3165 akr 15r DIR 0,10 0 1 inotify gvfs-gdu- 3192 akr 9r DIR 0,10 0 1 inotify gvfsd-tra 3187 akr 7r DIR 0,10 0 1 inotify hald 875 haldaemon 11r DIR 0,10 0 1 inotify ibus-engi 2861 akr 4r DIR 0,10 0 1 inotify ibus-gcon 2833 akr 4r DIR 0,10 0 1 inotify ibus-x11 2836 akr 5w DIR 0,10 0 1 inotify indicator 3301 akr 9r DIR 0,10 0 1 inotify init 1 root 5r DIR 0,10 0 1 inotify init 1 root 6r DIR 0,10 0 1 inotify nautilus 3096 akr 18u DIR 0,10 0 1 inotify polkitd 3162 root 5r DIR 0,10 0 1 inotify pulseaudi 2832 akr 13r DIR 0,10 0 1 inotify seahorse- 2906 akr 19r DIR 0,10 0 1 inotify sh 3164 akr 15r DIR 0,10 0 1 inotify sh 3763 akr 15r DIR 0,10 0 1 inotify udevd 441 root 6r DIR 0,10 0 1 inotify udevd 607 root 6r DIR 0,10 0 1 inotify udevd 608 root 6r DIR 0,10 0 1 inotify update-no 3126 akr 16w DIR 0,10 0 1 inotify
こんなに使われてるの?
いや、sh が使っているとは思えないから、fd が漏れてるのか?
アプリケーションが個々の画面を意識するには Xinerama や XRandR をつかえるらしい。
Xinerama な dual monitor な環境で、feh を full screen mode にするときに、常に最初の画面が使われてしまうという問題があったのだが、以下のようにしたら直った。とりあえずマニュアルに書いてある連絡先に送っておく。
diff -ru feh-1.3.4-/src/keyevents.c feh-1.3.4/src/keyevents.c --- feh-1.3.4-/src/keyevents.c 2005-07-14 20:59:03.000000000 +0900 +++ feh-1.3.4/src/keyevents.c 2010-01-03 06:08:14.764034775 +0900 @@ -385,10 +385,6 @@ if (opt.xinerama && xinerama_screens) { int i, rect[4]; - /* FIXME: this doesn't do what it should; XGetGeometry always - * returns x,y == 0,0. I think that's due to the hints being passed - * (or more specifically, a missing hint) to X in winwidget_create - */ winwidget_get_geometry(winwid, rect); /* printf("window: (%d, %d)\n", rect[0], rect[1]); printf("found %d screens.\n", num_xinerama_screens); */ diff -ru feh-1.3.4-/src/menu.c feh-1.3.4/src/menu.c --- feh-1.3.4-/src/menu.c 2005-07-14 20:59:03.000000000 +0900 +++ feh-1.3.4/src/menu.c 2010-01-03 06:08:30.180025354 +0900 @@ -2071,10 +2071,6 @@ if (opt.xinerama && xinerama_screens) { int i, rect[4]; - /* FIXME: this doesn't do what it should; XGetGeometry always - * returns x,y == 0,0. I think that's due to the hints being passed - * (or more specifically, a missing hint) to X in winwidget_create - */ winwidget_get_geometry(m->fehwin, rect); /* printf("window: (%d, %d)\n", rect[0], rect[1]); printf("found %d screens.\n", num_xinerama_screens); */ diff -ru feh-1.3.4-/src/winwidget.c feh-1.3.4/src/winwidget.c --- feh-1.3.4-/src/winwidget.c 2005-07-14 20:59:03.000000000 +0900 +++ feh-1.3.4/src/winwidget.c 2010-01-03 06:05:18.822031320 +0900 @@ -1004,6 +1004,7 @@ void winwidget_get_geometry(winwidget winwid, int *rect) { int bw, bp; + Window child; D_ENTER(4); if (!rect) return; @@ -1011,6 +1012,9 @@ XGetGeometry(disp, winwid->win, &root, &(rect[0]), &(rect[1]), &(rect[2]), &(rect[3]), &bw, &bp); + XTranslateCoordinates(disp, winwid->win, root, + 0, 0, &(rect[0]), &(rect[1]), &child); + /* update the window geometry (in case it's inaccurate) */ winwid->x = rect[0]; winwid->y = rect[1];
持ち歩いて、いくつかのネットワークに接続するマシンで、接続しているネットワークを自動的に判別したいとする。
その場合、DHCP で付与されたアドレスを調べれば、だいたい判別できる。
しかし、プライベートIPアドレスで、同じネットワークアドレスを使うネットワークが複数あった場合、アドレスだけでは判別できない。
そのようなときに使える方法としては、DHCP サーバの MAC アドレスを調べればいいのではないか。
DHCP でアドレスが付与されたということは、DHCP サーバと通信済みなので、(expire してなければ) arp テーブルに DHCP サーバの MAC アドレスはすでに載っていて、それを見ればよい。
DHCP サーバが頻繁にリプレースされる状況があるとうまくいかないが。
メモリをテストしてみようと考えて、memtest86+ を見に行く。
が、USB メモリに入れられる bootable イメージがない。ONKYO DX1007A5 は光学ディスクドライブがないので、USB メモリが便利なのだが。
ふと思いついて、memtest86 を見にいくと、こちらは USB メモリに入れられるイメージが用意されている。む、memtest86 3.5 は 4GB 以上のマシンでは動作しないバグがあるのか。3.4 なら問題ないらしい。
さて、どうするか。memtest86+ v4.00 (2009-09-22) のほうが新しいし良い感じがするけれど、memtest86 v3.4 (2007-12-27) なら USB メモリのイメージが用意されているし、悩みどころである。
優柔不断に悩んだ結果、memtest86 のイメージを書き込んだ後マウントして、memtest86+ のバイナリを加えて、syslinux.cfg にちょっと追加したら memtest86 と memtest86+ を選んで動かせるものができた。うむ。
USB メモリには、昔ジャンクで買った、容量が 16M というとても小さいものを使った。(たしか 100円だった気がする。) memtest を入れるにはこれで十分である。
なお、物理的なサイズがかなり大きいので、内容を書いた付箋を貼り付けておいた。付箋を貼れるだけのサイズがあるというのは利点と言えなくもない。
memtest86+ v4.00 を動かすと、
Athlon 64 (0.09) 1596MHz L1 Cache: 64K 12468MB/s L2 Cache: 512K 2418MB/s L3 Cache: None Memory: 3838M 2165MB/s Chipset: AMD K8 IMC (ECC: Disabled) Settings: RAM: 399MHz (DDR798) / CAS: 5-5-5-15 / DDR2 (128bits)
だそうだ。
ISO イメージから USB メモリ用のイメージに変換するソフトウェアもあるらしい?
1日動かしてもエラーは出ないのでメモリは問題ないようだ。
memtest86 v3.4 を動かすと、L1 Cache が 128K と出てくる。
memtest86+ v4.00 だと 64K なので異なる。
どちらが正しいか?
... lscpu, cpuid, x86info の結果 を見直すと、L1 Data cache と L1 Instruction cache がそれぞれ 64K ということなので、どちらも正しいのかもしれない。
あるいは、どちらも不正確というべきか。
Ubuntu で、ふと用意されている壁紙を見たら、横長の画像のサムネイルのリストが表示されて、選択すると全画面 (2732x768) に表示される。
縦横比もおかしくないし、2732x768 なんていうレアなサイズを用意しているとはすごい、と思ったが、/usr/share/backgrounds を覗いて実際のファイルを見ると、そんなことはない。用意されている画像の横幅は最大でも 1920 であり、横方向は拡大、縦方向は上下カットして表示しているようだ。
ONKYO DX1007A5 で VGA 出力を使ってみる。
プロジェクタにつないで、xrandr で様子を見てみると、CRT1 にちゃんと情報が出る。
% xrandr Screen 0: minimum 320 x 200, current 2732 x 768, maximum 2732 x 1536 LCD connected 1366x768+0+0 (normal left inverted right x axis y axis) 224mm x 126mm 1366x768 60.0*+ 1280x768 60.0 + 1280x720 60.0 + 1024x768 60.0 + 1280x600 60.0 + 1024x600 60.0 + 1024x480 60.0 + 800x600 60.0 + 800x480 60.0 + 720x480 60.0 + 640x480 60.0 + DFP1 connected 1366x768+1366+0 (normal left inverted right x axis y axis) 224mm x 126mm 1366x768 60.0*+ 1280x768 59.9 + 1280x720 60.0 + 1024x768 60.0 + 1280x600 60.0 + 1024x600 60.0 + 1024x480 60.0 + 800x600 60.3 + 800x480 60.0 + 720x480 60.0 + 640x480 60.0 + CRT1 connected (normal left inverted right x axis y axis) 1600x1200 60.0 + 1400x1050 60.0 1280x1024 60.0 47.0 43.0 1440x900 59.9 1280x960 60.0 1366x768 59.9 1280x800 60.0 1152x864 60.0 47.0 43.0 1280x768 59.9 1280x720 60.0 50.0 1024x768 60.0 43.5 1280x600 60.0 1024x600 60.0 1024x480 60.0 800x600 60.3 56.2 47.0 800x480 60.0 720x480 60.0 640x480 60.0
LCD が左画面、DFP1 が右画面、CRT1 がプロジェクタである。このプロジェクタは 1600x1200 まで出せるようだ。
さて、では有効にしてみよう、ということで以下のようにするがうまくいかない。
% xrandr --output CRT1 --auto xrandr: cannot find crtc for output CRT1
どうも、Radeon HD 3200 は出力パイプラインが 2本なので、左右 2画面に加えて外部の VGA 出力を行うのは無理らしい。
以下のように DFP1 (右画面) を切ってからなら動作する。
% xrandr --output DFP1 --off % xrandr --output CRT1 --auto
ここで動作するというのは、1600x1200 の画面が CRT1 に表示され、その左上 1366x768 が LCD に表示されるということである。
X からみると、1600x1200 なスクリーンが 1枚になる。
% xdpyinfo|grep dim dimensions: 1600x1200 pixels (420x315 millimeters)
そうじゃなくて、別の画面にしてみようということで、以下のようにするとエラーである。なにか大きすぎるらしい。
% xrandr --output LCD --left-of CRT1 xrandr: screen cannot be larger than 2732x1536 (desired size 2966x1200)
では、ということで CRT1 にすこし小さいモードを指定するとうまくいく。
% xrandr --output CRT1 --mode 1280x1024 % xrandr --output LCD --left-of CRT1
これで、LCD の右側に CRT1 が配置されたかのような動作になった。
X 的には、2646x1024 になる。つまり 1366+1280 x max(768,1024) ということであろう。
% xdpyinfo|grep dim dimensions: 2646x1024 pixels (685x265 millimeters)
ただ、この状態では、CRT1 は右がすこし欠けてしまった。
1280x1024 などという変な解像度にしたからか、と思って 1024x768 に指定するときれいに出た。
% xrandr --output CRT1 --mode 1024x768
他の解像度も指定して見ると、このプロジェクタは 4:3 じゃない解像度を指定すると、4:3 になるようにアスペクト比を変えるようだ。1280x600 を指定して xclock を出すと、時計があからさまに楕円になる。
OpenOffice.org Impress で、Slide Show が左側の画面にいってしまうようだ。
つまり、これで、LCD の右側に CRT1 を配置しておくと、LCD に表示されてしまい、CRT1 には表示してくれない。
feh の問題と似た挙動である。
もしプレゼンするなら、CRT1 は LCD のさらに左側に配置したほうがいいかもしれない。(このマシンでプレゼンする予定はないけれど)
つまり、こうである。
% xrandr --output LCD --right-of CRT1
こうすれば、OpenOffice.org 3.1 Impress の Slide Show は CRT1 に出る。
あと、無線LAN を試してみると、これは問題なく使えた。
ただ、本体左側の RF スイッチを ON にして、BIOS で WLAN status を Enable にしておく必要はある。
ちなみに、--left-of と --right-of と同様に、--above と --below もあって、縦に並べることもできる。
しかし、GNOME のデフォルトのパネルの配置のままだと、(Mac の UI のいいかたをすれば)「高さ1マイルのメニューバー」という性質が壊れてしまう。
1366x768 は「フルワイドXGA」というのだそうな。
% ruby -e 'p 1366*9/16.0' 768.375
というように、ほぼ 16:9 になるようにしてあるらしい。
プライベート IP アドレスなネットワークがふたつあるとしよう。ふたつのネットワークは、(残念なことに) 両方とも 192.168.0.0/24 を使っちゃっているとしよう。
両方のネットワークでは DHCP が動いていて、接続したマシンは動的に IP アドレスが割り振られ、そのアドレスは固定していないということにしよう。
ネットワークそれぞれに NAT を行うゲートウェイがあって、各ネットワークの中から外へは接続できることにしよう。
これに対し、外から中にアクセスするには、まずゲートウェイに ssh で接続して、そこからさらに内部へ接続するということにしよう。またゲートウェイは固定なグローバル IP アドレスを持っているとする。
そして、複数台のマシンがあり、それらのマシンは気分によってどちらかのネットワークに接続されるということにしよう。
この状況で、それらの各マシンが相互に簡単に ssh できるようにするにはどうしたらいいか。
まず、IP アドレスは必要だろうから、DHCP でアドレスを割り当てたときに、DDNS (Dynamic DNS) で登録しておくことを考える。(DHCP サーバ側がやってもいいし、割り当てられたマシン側でやってもいい。)
しかし、ssh でつなぐには、ssh 先の IP アドレスだけでなく、それが同じネットワークに属しているかどうかを知らなければならない。同じネットワークなら直接その IP アドレスに接続すればいいが、違うネットワークならゲートウェイ経由でその IP アドレスに接続する必要がある。そのどちらかであるか判断するのが問題である。判断さえできるなら、その判断を行って接続を行うプログラムを ProxyCommand に指定すればいい。
しかし、相手がどのネットワークに接続しているかを判断するのに同じ方法は使えない。IP アドレスは DDNS で登録されているので分かるとしても、接続してもいない相手の arp テーブルを覗くのは無理である。そして、IP アドレスだけでは、ネットワークを判断できない。これは、両方のネットワークが同じ 192.168.0.0/24 を使って衝突しているからである。
さて、どうするか。DDNS で、hostname.domain の他に hostname-network.domain にでもネットワークの情報も登録するというのも考えられるが、なんか大仰である。
しばらく考えて、127.0.0.0/8 の中に変換してしまえばいいのではないかと思いついた。つまり、ネットワーク1 の 192.168.0.x は 127.0.1.x に変換し、ネットワーク2 の 192.168.0.x は 127.0.2.x に変換する。こうやって変換しておけば、127.0.1.x と 127.0.2.x の違いからネットワークの違いを判断できる。そして、このアドレスは ProxyCommand に指定したプログラムでしか使わないので、そのプログラムが逆変換すれば実際の IP アドレスも得られて問題ない。
127.0.0.0/8 はまるごと ループバックアドレスなのだが、ふつうは 127.0.0.1 しか使わないので、他をこうやって使ってもあまり問題はないのではないか。
中継を行うには、ProxyCommand で ssh した向こう側で標準入出力を TCP 接続につなげるコマンドを起動する。
これを行うのは (終了のところ以外は) 難しくなく、自分で書いてもいいが、難しくないだけに多くのツールがある。
個人的には昔は socket コマンドを使っていて、ここしばらくは netpipes の hose を使っていたが、ちょっと調べてみると、もっといろいろあるようだ。
とりあえず Debian パッケージをちょっと調べただけだが、他にももっとあるに違いない。
どれがよく使われているのかと思って、Popularity contest を見てみる。
うぅむ。socket や netpipes はやはりマイナーだったのだな。そこはかとなくそうかもしれないとは感じていたが。
ところで、この処理を行うのに、終了のところは微妙である。
TCP は双方向通信路であり、その片方向を閉じる half close があるので、それを考えて素直に書くと、
というようになるが、やってみるとこれは不便である。
どう不便かというと、たとえば SMTP で QUIT コマンドを送っても中継プロセスが終了しないのである。QUIT を送ると SMTP サーバはソケットを close し、中継プロセスはソケットから EOF を検知し stdout を close する。つまりサーバからクライアントへの通信はちゃんとここで終わる。しかし、逆方向の、クライアントからサーバへの通信が終わっていることを中継プロセスはこの時点では知ることができない。そのため、プロセスは終わらず、標準入力からの入力を待ってしまう。
サーバのソケットは close されているので実際にはもうデータを受け付けないわけだが、それを知るには実際にデータを送って、それがはじかれて RST パケットが戻ってきて、その後でもう一回データを送るとエラーになってやっとアプリケーションが知ることができる。(TCP のステートマシンの状態を見張れば、RST が戻ってきた時点でわかるのでふたつめの送信は省けるが、最初のはどうしようもない。なおステートマシンの状態はポータブルには調べられない。)
このため、ここにはトリックが必要で、socket コマンドはソケットが EOF になったら即座にプロセスが終了するようになっている。
また、netpipes の hose は終了時の挙動を --slave, --netslave, --netslave1, --netslave2 というオプションで制御できる。
同様に tcputils の tcpconnect は -i, -r で制御できる。
まぁ普通に考えられる対処はこんなものかな、と思っていたのだが、socat はタイムアウトを使っているようだ。デフォルトでは、一方の通信が終わったら、0.5秒後に逆方向も閉じて終わる。これは良いアイデアな気がする。
socat はなんか多機能で楽しいな。readline も使えるし。
記述がちょっと煩雑なのが難点だが。
迷路を解く問題か。
A* (やダイクストラ法) はあとから priority を変えられる priority queue がないと気分良く書けないので、そういう用意がなければ微妙な所ではある。
ダイクストラ法 (や A*) は、隣接するノード間の距離が一定でない場合を扱えるので、あるノードに到達するパスで、先に見つかったパスよりも短いパスが後から見つかることがある。
たとえば、
graph.asy:
size(100mm,100mm); void node(pair p, string s) { filldraw(shift(p)*scale(0.2)*unitcircle, white); label(s, p); } void line(pair p, pair q, string s) { draw(p--q); label(s, (p+q)/2+(0.1,0.05)); } pair s = (0,10); pair a = s + 1*dir((-1,0)); pair b = s + 2*dir((2,-1)); pair c1 = a + 3*dir((2.6,-2)); pair c2 = b + 1*dir((-0.9,-2)); pair c = (c1+c2)/2; pair g = c + 1*dir((0,-1)); line(s, a, "1"); line(s, b, "2"); line(a, c, "3"); line(b, c, "1"); line(c, g, "1"); node(g, "G"); node(c, "C"); node(a, "A"); node(b, "B"); node(s, "S");
というグラフで、優先順位付きキューに S だけが入っている状態から探索をはじめる。S の優先順位は 0 である。(優先順位は小さいほど優先されるとする)
この時点でキューに入っている S の中では S が最優先なので、S を取り除き、S から隣接するノードを調べると、A, B が見つかる。A を優先順位 1 でキューに入れ、B を優先順位 2 でキューに入れる。
この時点でキューに入っている A, B の中では A が最優先なので、A を取り除き、A から隣接するノードを調べ、C が見つかるが、ここで見つかった、S から A を経由して C に到達する距離は 1 + 3 = 4 である。C を優先順位 4 でキューに入れる。
この時点でキューに入っている B, C の中では B が最優先なので、B を取り除き、B から隣接するノードを調べ、C がまた見つかる。ここで見つかった、S から B を経由して C に到達する距離は 2 + 1 = 3 である。
ここで、単純に C を優先順位 3 でキューに入れる、と、キューの中で C がふたつになってしまう。さりとて、S-A-C よりも S-B-C のほうが短いので、後から見つかった S-B-C を捨てるわけにもいかない。というわけで、すでにキューに入っている要素の優先順位を書き換える必要が出てくる。
さて、しかし、この迷路の話では斜めには動けないので、隣接するノード間の距離は一定である。
ノード間の距離が一定の場合、後から短いパスが見つかるということはない。そうすると、ダイクストラ法は幅優先探索に等しくなる。
というわけで、この問題にダイクストラ法を適用すると幅優先探索になってしまうので、ダイクストラ法という選択に意味があるだろうか。
なお、A* はヒューリスティック関数によりダイクストラ法よりもマシな探索をするので、その選択には意味がある。
ダイクストラ法に意味があるとしたら、将来への布石だろうか。斜め移動 (距離は sqrt(2)) のサポートが予期されているとか。
既出だったか。
真面目に使う予定もないのだが、ふと GPSロガー (M-241) を買ってしまった。
とりあえず半日動き回った後、USB でつないで
% gpsbabel -t -w -i m241 -f /dev/ttyUSB0 -o kml -F out.kml
としてデータを kml という形式で取り出し、
Google Earth に読み込ませたらなんとなく移動経路が表示できた。
その kml ファイルを HTTP で公開して、Google Maps でその URL を指定すると、Google Maps でも同様に表示できた。
M-241 は Bluetooth でつながるようだが、オンキョー DX1007A5 の Bluetooth デバイスは Ubuntu 9.10 (karmic) の linux kernel では使えないようだ。
lsusb で
Bus 003 Device 002: ID 0cf3:3000 Atheros Communications, Inc.
と出てくるのを手がかりに検索すると、 <URL:http://lkml.org/lkml/2010/1/6/102> に投稿されているドライバが見つかった。
うぅむ。今年のメールだな。
知らなかったのだが、奥行きを感じる能力を深視力とか深径覚といい、それがうまく感じられないことを深視力不良というらしい。
feh は反応がないので debian のほうにも報告してみる。
Debian BTS #567297: feh full screen mode always use the first screen in Xinerama
こちらはすぐに反応があって、upstream は動いていないとのこと。まぁ、そうだろうとは思っていた。
1.9.2 の Time が遅いのは、Fixnum が 31bit の環境では、そうだろうな。Fixnum が 63bit あれば遅くないはずだが。
31bit の環境でも 64bit 演算を Time 内部でやるようにしようかと思いつつもやっていない。
[latest]