-277
binary - よりポータブルな無限ループという記事があったので,Plan9で試してみた.
コンパイル通ったと思ったら,ファイルは空で,実行できなかった.
cpu% cat infinite.c int main=-277; cpu% 8c infinite.c cpu% 8l infinite.8 cpu% 8.out 8.out: '/bin/8.out' file does not exist cpu% ls -l 8.out --rwxrwxr-x M 1832969 oraccha oraccha 0 Dec 24 18:48 8.out
アセンブリをみると,mainがテキストじゃなくてデータセクションになっているね.
cpu% 8c -S infinite.c DATA main+0(SB)/4,$-277 GLOBL main+0(SB),$4 END ,
上の実行例で奇妙なのは,ファイルが空だけど,存在するのに,"file does not exist"になること.次のように,"./"をプレフィックスすると予想通りのエラーメッセージを返す.
cpu% ./8.out ./8.out: exec header invalid
不思議だけど,ここでシステムコールのエラー処理について横道にそれる.システムコールがエラーで終了した場合,UNIXではerrnoという整数値にその原因がセットされるが,Plan9では,文字列でセットされる.errnoはライブラリが保持するグローバル変数だけど,Plan9の場合は,カーネルのプロセス構造体(struct Proc)の中にエラー文字列を保持する領域(syserrstrの先のerrbuf0かerrbuf1に格納されている)があって,errstr(2)システムコールによってその文字列を取り出す.
9/port/portdat.h: 612: struct Proc 613: { 697: char *syserrstr; /* last error from a system call, errbu\f0 or 1 */ 698: char *errstr; /* reason we're unwinding the error stack, errb\uf1 or 0 */ 699: char errbuf0[ERRMAX]; 700: char errbuf1[ERRMAX];
UNIXでもおなじみのperror()の実装は次のようになっている.10行目でerrstr()を呼んでいる.
libc/port/perror.c: 4: void 5: perror(char *s) 6: { 7: char buf[ERRMAX]; 8: 9: buf[0] = '\0'; 10: errstr(buf, sizeof buf); 11: if(s && *s) 12: fprint(2, "%s: %s\n", s, buf); 13: else 14: fprint(2, "%s\n", buf); 15: }
(追記 2007-01-06) Cがダメなら,アセンブリで書けばいいんだけど,やるだけ野暮ってもんか.
cpu% cat infinite.s TEXT _main(SB),$0 WORD $-277; cpu% 8a infinite.s cpu% 8l -o infinite infinite.8 cpu% infinite