12/31 (月)
さらば hp deskjet 948c
年賀状を印刷しようと本棚の上にしまってあった hp のインクジェットプリンタを取り出す。 が、 OCUH!! 印字が出来なくなっているYO。 hp deskjet 948c は2002年の夏に購入したのだが、 2004年の1月に部屋を引越し後は 一度も使わずにいたのが不味かったのか…
まずインクジェットのカートリッジを疑ってみることにし、
替えのカートリッジを買うために秋葉原まで出張るのだが…
ソフマップ本店には
「型が古すぎてカートリッジがない」と言われる。
とすると hp deskjet 948c は
2002年の夏の暑中見舞い、2003年の年賀状ぐらいしか印刷していないのに、
もうお払い箱ですが…
ランニングコストが100円/枚じゃすまないですけど…
トホホ。
ふとお店の周囲を見渡すと、 どのメーカーの製品もプリンタ+スキャナが合体した複合機が主力で、 お値段も2〜3万円になっている。 なんか私が知らないうちにプリンターの跳躍進化が起きていたらしい。
p.s.
久しぶりに秋葉原の街に出たが、 ソフマップが異常繁殖している。 ヤマギワが全部ソフマップになったからかしら。
12/25 (火)
[Linux] /proc/<pid>/{stat,status} の下のシグナル情報
Linux カーネルの procfs は、 /proc/<pid>/stat または /proc/<pid>/status でシグナルの状況を通知してくれる。 ただ、 実際に返す情報がマニュアルの記述 (proc(5))と 少し異なるようだ。
/proc/<pid>/stat の場合は、 以下のようになる。
- signal %lu
-
「The bitmap of pending signals.
待機中のシグナルのビットマップ。」
これは説明そのまま。 - blocked %lu
- 「The bitmap of blocked signals.
ブロックされた (blocked) シグナルのビットマップ。」
とあるが、実際はこのスレッドがブロックしているシグナルのビットマップ。 - sigignore %lu
- 「The bitmap of ignored signals.
無視された (ignored) シグナルのビットマップ。」
とあるが、実際はこのプロセスがハンドラに SIG_IGN を設定しているシグナルのビットマップ。 - sigcatch %lu
- 「The bitmap of caught signals.
キャッチされた (caught) シグナルのビットマップ。」
とあるが、実際はこのプロセスが(ハンドラを設定して)補足するシグナルのビットマップ。
signalの項以外は、 sigaction や sigprocmask で設定されたシグナルの設定を返していて、 シグナルが送信されたかどうかでは変化しない。
/proc/<pid>/status は /proc/<pid>/stat よりも少し情報量が多い。
SigPnd: 0000000000000000 スレッドに送られたシグナルのうち待機中のシグナルのビットマップ ShdPnd: 0000000000000000 プロセスに送られたシグナルのうち待機中のシグナルのビットマップ SigBlk: 0000000000000000 スレッドがブロックしているシシグナルのビットマップ SigIgn: 0000000000000000 プロセスが無視しているシグナルのビットマップ SigCgt: 0000000000000000 プロセスがハンドラを設定しているシグナルのビットマップ
各シグナルはデフォルト(SIG_DFL)、無視(SIG_IGN)、捕捉(ハンドラ設定)の3つの状態を持つが、
- SIG_DFL の場合は SigIgn と SigCgt が 両方ゼロに
- SIG_IGN の場合は SigIgn だけが1に
- ハンドラ設定の場合には SigCgt だけが1に
と表示される。
12/24 (月)
新装「ブックファースト渋谷店」に行って来た
ブックファースト渋谷店の旧店舗は 10月14日に閉店したが、 新しい旭屋書店渋谷店跡地に新しい店舗が開店。 渋谷に出たついでに新しい店舗に初めて寄ってみる。
旧店舗よりは格段に狭くなっていて、 専門書の類が大幅に削減されていて涙。 検索端末は残っているので、 目的の本がどこにあるのかを探すのは便利だけど、 在庫そのものがだいぶ圧縮されているので 過去にあった本がなくなっているよ(;_;
このぶんだと 私の欲しい本を探すには新宿か神保町か秋葉原に出るしかなさそうだ。 む〜。
12/20 (木)
[Prog] printf 関数をちゃんと使おう
他の人が書いた C 言語のプログラムを見ながら思ったのだが、
strcat
や strcmp
で文字列を切り貼りするのは止めて、
printf
はフォーマット文字列をちゃんと使おう。
右寄せ・左寄せ・インデントが必要な場合でも、
1行を表示するのは1回の printf
呼び出しで間に合う場合がほとんどだよ。
文字列を表示する
printf を使った文字列の表示は、
単純な %s
に幅指定を行うことで
「詰めもの」をしたフォーマットが可能だ。
// 普通に表示 printf("A %s.\n", "01234567890123456789"); // 最小幅を指定 (右詰, 隙間は空白文字) printf("B %30s.\n", "01234567890123456789"); // 最小幅を指定 (左詰, 隙間は空白文字) printf("C %-30s.\n", "01234567890123456789"); // 最大幅を指定 (入力文字列の10文字分を表示) printf("D %.10s.\n", "01234567890123456789"); // 最大幅と最小幅を同時に指定 (入力文字列の10文字分を30文字の中で右詰表示) printf("E %30.10s.\n", "01234567890123456789"); // 最大幅と最小幅を同時に指定 (入力文字列の10文字分を30文字の中で左詰表示) printf("F %-30.10s.\n", "01234567890123456789");
このプログラムを実行すると以下のようになる。
A 01234567890123456789. B 01234567890123456789. C 01234567890123456789 . D 0123456789. E 0123456789. F 0123456789 .
幅を引数で指定
さらに数字を書くべきところを *
にすることで、
引数を使った「幅」の指定が可能になる。
// 最小幅を引数で指定 printf("G %*s.\n", -40, "01234567890123456789"); // 最大幅を引数で指定 printf("H %.*s.\n", 10, "01234567890123456789"); // 両方を指定 printf("I %*.*s.\n", -20, 10, "01234567890123456789");
このプログラムを実行すると以下のようになる。
G 01234567890123456789 . H 0123456789. I 0123456789 .
引数を任意の順番に並べる
printf 関数の引数はフォーマット文字列の並びに並べるのが普通だが、%
の後に n$
を置くことで、引数の位置を変更することができる。
printf("%3$d %1$s %2$f\n", "abc", 1.4, 1234);
このプログラムは以下のように出力される。
1234 abc 1.400000
幅指定の位置を変更することも可能だが。
printf("%2$*1$d.\n"%, 10, 20); printf("%1$*2$d.\n"%, 10, 20);
このプログラムは以下のように出力される。
20. 10.
桁区切り
%u
、%d
、%f
などの 10 進表示の場合、3桁ごとにカンマ(,)で区切ることができる。
これは %
と型指定子の間に '
をつける。
printf("%d -> %'d\n", 12345678, 12345678); printf("%f -> %'f\n", 9999.9999, 9999.9999);
このプログラムは以下のように出力される。
12345678 -> 12,345,678 9999.999900 -> 9,999.999900
ただし 3 桁ごとの区切りが可能かどうか、また区切り文字が何になるかはロケールの LC_NUMERIC
に依存する。
例えばロケールに C
が指定されていると、桁区切りは出力されない。
#include <locale.h> setlocale(LC_NUMERIC, "C");
12/19 (水)
12/17 (月)
[Food] うなぎ桜家@三島 (公式、livedoor東海グルメ、食べログ.com)
久しぶりの沼津出張だったので、 うなぎを食べませうと同僚と三人で三島の老舗「うなぎ桜家」へ行きます。 安政三年創業だそうです。 ちなみに前回の三島でウナギは、 2006年12月28日に水泉園でした。
1時過ぎにお店に着いたものの、 店の前で随分待たされます。
同僚二人はうな丼は、私は奮発してうな重を頼みます。
うなぎはふっくらと脂がのって大変美味。 うま〜です。 タレは少し辛口で、テーブルに置いてあるので自由にかけて食べれます。
三島のうなぎ屋さんは山椒を置いているところ、 置いてないところがあるのかしら?
12/10 (月)
フリンダース・ピートリーとストーンヘンジ
山岸 凉子の「ツタンカーメン」の中に、 主人公ハワード・カーターの師としてエジプト考古学の大家 フリンダース・ピートリー(Sir WM Flinders Petrie)が登場する。 ピートリーは作中では職人肌な老学者として描かれている。 さらに新潮版社の文庫版の3巻には 荒俣 宏が解説によるとこんな感じの人らしい。
たとえば、カーナボン卿は、遺跡発掘の現場をまかせる監督として、 当初は若いカーターではなく、 力のあるエジプト学者を想定していた。 その筆頭にあがったのが、山岸さんも描いているように、 ロンドン大学のエジプト学講座主任を長年つとめたフリンダース・ピートリーだった。 このピートリーが、まさに「発掘師」たちの集団を「考古学者」の組織に変える役割を果たしたのだが、 ピートリーを講座の主任に指名したのはアメリア・B・エドワーズという奇妙な女流作家だった。ここにもまたロマンがある。
エドワーズは幼い頃、古代エジプト遺跡を巡る旅の本に心惹かれ、 長じて自らも現場を訪れた。 そして前述した建築家バリーが遺跡に自分の名を落書きしていた光景を目撃し、 放っておくと人類の遺産消滅するのではないかという危惧を味わった。 そこでエドワーズはイギリス中を講演して回り、 古代遺跡の保存を訴えた。 そして乏しい私財を投げうち、ロンドン大学内にエジプト学講座を開設した。 この講座を介して、宝探しではない考古学のフィールドワーカーを教育し、 同時に遺跡の保護を訴えつづける宣伝機関というべき講座を立ち上げた。 そのとき講座のトップとして白羽の矢が立てられたのが、ピートリーだった。 ハワードが学んだ師の一人に、ピートリーがいたからこそ、 純真で若い考古学者の主人公ハワード・カーターが生まれ育つことになったのである。
ツタンカーメン (3) 解説:イギリスの側から見れば……
というわけで、 ピートリーにはお堅い学者という山岸漫画のイメージがこびりついていたが、 意外にも数字マニアな側面があるようだ。
ピートリーは1880年〜1881年にピラミッドの正確な測定を行っている。 これはピラミッドの数字には宇宙の秘密が隠されているという「ピラミッド神秘学」に 反発しておこなったのかと思っていたのだが、 最近「古代文明の謎はどこまで解けたのか」を読み直して ピートリーがストーンヘンジの研究を手がけていたことを知る。
ペトリーはまた、ストーンヘンジの年代を決めるのに独特の方法を採用した。 このモニュメントの配置が、特定の日の太陽の方向に基づいていると仮定したのだ。 大トリリトンからヒールストーンの彼方を見た方向に夏至の日の出が一致する年代を計算することで、 ペトリーはサーセン石の馬蹄形の製造年代を紀元730年と推定した。 このことは、サクソン人が建造したことを意味する。
古代文明の謎はどこまで解けたか (1) 失われた世界と驚異の建築物・篇けたか P.268
まるで オリオン・ミステリーのロバート ボーヴァルや、 ペルーのカラササヤ遺跡に関するポナンスキー説の走りのように読める。 ピートリーはどこまで真剣だったのだろうか?
12/8 (土)
[Prog] 動的生成コードのフレームをデバッガで表示する
動的生成コード(dynamically genarated code) とか ランタイム生成コード(runtime generated code)とかよばれるもの、 つまり JIT コンパイルとか動的バイナリ変換とか dynamic weaving で生成されるコードは デバッガからうまく表示されない。
例えばサンプル1は 静的に生成された関数をメモリ上でコピーして、 そこに無理矢理ジャンプして実行するサンプルコードだ。 このコードを実行した場合、以下のようにフレームが積まれる。
#0 cause_null_exception() #1 (動的生成コード) #2 test() #3 main()
ところがぎっちょんちょん。 gdb 上でサンプルプログラムを動かすと 動的生成コードより下はフレームが壊れて見えない。
#0 cause_null_exception (a=0) at runtime-generated-code3.c:42
#1 0xb7fbc011 in ?? ()
#2 0x00000000 in ?? ()
#0 cause_null_exception (a=0) at runtime-generated-code3.c:40 #1 0x2000000000044070 in ?? () #2 0x2000000000044070 in ?? () #3 0x0000000000000000 in ?? ()
動的コードを実行しているフレーム自身は仕方ないが、 それよりも下のフレームが gdb から見て表示不能になっているのはイクナイ。
Libunwind ライブラリを使う
このような問題を解決する場合、 libunwind というライブラリを使える。
libunwind(3)ライブラリは i386/Linux、x86_64/Linux、ia-64/HP-UX、ia-64/Linux で使える アンワインディング操作ライブラリ。 さらに libunwind には libunwnid-dynamic(3) という 動的生成コードの位置情報を登録する機能が用意されており、 正しい unwind 情報を持っていないコードでも操作可能になる。
ただし libunwind(3) は比較的プラットフォームから独立した API だが、 libunwnid-dynamic(3) を使うにはプラットフォームにベッタリのコードになる。 とりあえずサンプル1を IA-64 上で _U_dyn_register するコードを書いてみる (サンプル2)。 _U_dyn_register で登録したコードは libunwind を使わないとアンワインディングできない のだが、 幸い IA-64/Linux は gdb は libunwind 対応の形でビルドされている(ことが多い)。
サンプル2を -lunwind をつけてビルドしたバイナリを gdb 上で実行すると、 青字のように動的生成コードよりも下のフレームがちゃんと表示されるようになった。
#0 cause_null_exception (a=0) at runtime-generated-code2.c:40 #1 0x2000000000044070 in ?? () #2 0x4000000000001170 in test () at runtime-generated-code2.c:113 #3 0x40000000000011d0 in main (argc=1, argv=0x60000fffffffb178) at runtime-generated-code2.c:118
i386 でも libunwind + gdb で動的生成コードを表示する手法があるはず。 現在調査中。
追記:12/31
i386 で動的生成コードを表示する方法は見つからず。
12/5 (水)
[Prog] プロセス間同期オブジェクトを掴んだままプロセスが死亡した場合
アプリケーションの機能を複数のプロセスに分けて実装し、 個々のプロセスが異常停止した場合でもリカバリーさせることを考えてみる。 プロセス間では同期処理が必要だが、 古典的には System V の IPC セマフォやメッセージキューを使用することになる。
これらの System V IPC の同期オブジェクトは、 プロセスが終了したの動作がきちんと定義されている。 System V セマフォの場合には semaop に SEM_UNDO が指定された場合はその操作が取り消され、 指定されない場合はそのままとなる。 セマフォを使った排他処理を行うなら、 プロセスが死亡した時に自動的に解除するか、 ロックしたままにして別プロセスから回復処理を行うかを選択可能だ。
一方、Pthread の同期オブジェクトや POSIX セマフォはどうだろう? 比較的新しい pthread mutex は process-shared 属性を設定することで プロセス間で使用可能な mutex を作成できる。 しかし process-shared な mutex は、 ロックをとったままのプロセスが死亡した場合の動作がハッキリしない。
とりあえず テストコードを書いて 確認してみよう。
OS | Arch | Library | Result |
---|---|---|---|
RedHat Enterprise Linux 4 (U4) | i386 | glibc 2.3.4 | プロセス死亡時にはロックは解除されないが、別プロセスによって解除可能 |
Vine Linux 4.1 (2.6.16-0vl76.3) | i386 | glibc 2.3.4 | setpsharedが動かない |
HP-UX 11i (B.11.23) | ia-64 | プロセス死亡時にはロックは解除されないが、別プロセスによって解除可能 |
12/2 (日)
日本の洪水伝説
常々 世界各地に洪水伝説が残っているが、 日本にはこれといった洪水伝説が残っていない。 と、思っていたのだが 八丈島には丹那(タナ)婆伝説 (Google)というのが伝わっているそうだ。
丹那婆伝説は八丈島の始祖伝説で 「大津波で島民がみな流される中で一人生き残ったタナという妊婦が男子を産み、 その子と母子交合して子孫を増やした」という伝説である。 洪水伝説でただ一人生き残って 近親相姦的に増えていくというのは 他の洪水伝説(インドのヌマ伝説とか)にも見られるモチーフ。
ただ丹那婆伝説も大津波の話のようだ。 日本では洪水というと鉄砲水か津波になって、 「何十日も大地が水浸しになる」という伝説にはリアリティがないんだろうなぁ。
12/1 (土)
[Prog] C++ で sizeof を使った時に警告
下のプログラムは g++ だと 3.3.6 でも 4.0.6 でも
invalid access to non-static data member 'Klass::member2' of NULL object
(perhaps the 'offsetof' macro was used incorrectly)
と怒られてしまう。
Klass のメンバ変数 inner2 が private 変数なのが問題のようだが、 静的メンバ関数中なんだから文法違反ということはない。 なんか同種の警告をよく目にするのだが、ちょっと過剰な警告表示のような気がする。
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stddef.h> class InnerKlass { public: uint64_t member1; }; class Klass { private: uint64_t member2; InnerKlass inner; public: static Klass* adjust_offset(InnerKlass* p); }; Klass* Klass::adjust_offset(InnerKlass* p) { return (Klass*)((char*)p - offsetof(Klass, inner)); }
追記:2008年7月4日
解決方法が分かった。 2008年7月4日の日記に記述。