コース目次 / 第1章
write(2)だけのhelloを、straceで見る
write()のみを呼ぶ最小限のプログラムを書き、straceで全システムコールを観察します。想像以上に多くの下準備が行われていることを確認し、-e trace=で目的のシステムコールだけに絞り込みます。
write(2)だけの、最小限のプログラム
hello.c として保存します。printfすら使わず、システムコールを直接呼ぶwrite()関数だけを使います。
#include <unistd.h>
int main(void) {
const char msg[] = "hello, syscall\n";
write(1, msg, sizeof(msg) - 1);
return 0;
}
gcc -O0 -o hello hello.c
./hello
hello, syscall
straceで、全部見る
strace ./hello
execve("./hello", ["./hello"], 0x7fff36c22010 /* 129 vars */) = 0
brk(NULL) = 0x56167c0a4000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f150367a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
...(中略、動的リンカがlibcを読み込む一連のシステムコール)...
write(1, "hello, syscall\n", 15hello, syscall
) = 15
exit_group(0) = ?
+++ exited with 0 +++
たった1回のwrite()を呼ぶためだけのプログラムなのに、30近いシステムコールが動いていました。その大半は、動的リンカ(ld.so)が共有ライブラリ(libc)を探し、読み込み、メモリに配置するための下準備(openat・mmap・mprotectなど)です。あなたが書いたコードが動き出す前に、これだけの仕事がOSとの間で交わされています。
目的のシステムコールだけに、絞り込む
strace -e trace=write ./hello
write(1, "hello, syscall\n", 15hello, syscall
) = 15
+++ exited with 0 +++
-e trace=writeで、writeシステムコールだけに絞り込めました。実際の調査では、こうして関心のあるシステムコール(ファイル操作ならopen,read,write、ネットワークならsocket,connect,send,recvなど)だけに絞るのが定石です。
こうなっていればOK
卒業まであと2章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。