コース目次 / 第1章

write(2)だけのhelloを、straceで見る

write()のみを呼ぶ最小限のプログラムを書き、straceで全システムコールを観察します。想像以上に多くの下準備が行われていることを確認し、-e trace=で目的のシステムコールだけに絞り込みます。

第1章 / 全4章目安 約12分この章のゴール: straceで全システムコールを観察し、目的のものに絞り込めるようになる

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章です。

この章はまだ完了していません。