プログラムが実行するシステムコールを確認する場合は、「strace」コマンドを使用します。
簡単なプログラムを確認してみる!(echo)
画面に文字を出力するみのechoコマンドでstraceを実行してみます。
$ strace echo aaa execve("/usr/bin/echo", ["echo", "aaa"], 0x7ffd6a2bd248 /* 54 vars */) = 0 brk(NULL) = 0x5579614ee000 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffecf0642d0) = -1 EINVAL (Invalid argument) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc43f000 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 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=87699, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 87699, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcbbc429000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0i8\235HZ\227\223\333\350s\360\352,\223\340."..., 68, 896) = 68 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2216304, ...}, AT_EMPTY_PATH) = 0 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcbbc201000 mmap(0x7fcbbc229000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7fcbbc229000 mmap(0x7fcbbc3be000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fcbbc3be000 mmap(0x7fcbbc416000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7fcbbc416000 mmap(0x7fcbbc41c000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc41c000 close(3) = 0 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc1fe000 arch_prctl(ARCH_SET_FS, 0x7fcbbc1fe740) = 0 set_tid_address(0x7fcbbc1fea10) = 11923 set_robust_list(0x7fcbbc1fea20, 24) = 0 rseq(0x7fcbbc1ff0e0, 0x20, 0, 0x53053053) = 0 mprotect(0x7fcbbc416000, 16384, PROT_READ) = 0 mprotect(0x55795f560000, 4096, PROT_READ) = 0 mprotect(0x7fcbbc479000, 8192, PROT_READ) = 0 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0 munmap(0x7fcbbc429000, 87699) = 0 getrandom("\x0c\xde\xfc\xfa\x80\xc5\xf7\xcc", 8, GRND_NONBLOCK) = 8 brk(NULL) = 0x5579614ee000 brk(0x55796150f000) = 0x55796150f000 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=6784496, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 6784496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcbbbb85000 close(3) = 0 newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0 write(1, "aaa\n", 4aaa ) = 4 close(1) = 0 close(2) = 0 exit_group(0) = ? +++ exited with 0 +++
別なコマンドを実行してみる!(locale)
少し動作が多くなるlocaleコマンドで実行してみます。
$ strace locale execve("/usr/bin/locale", ["locale"], 0x7ffd794db690 /* 54 vars */) = 0 brk(NULL) = 0x55c85ebe5000 arch_prctl(0x3001 /* ARCH_??? */, 0x7fff6c005920) = -1 EINVAL (Invalid argument) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82f8f69000 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 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=87699, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 87699, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f82f8f53000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0i8\235HZ\227\223\333\350s\360\352,\223\340."..., 68, 896) = 68 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2216304, ...}, AT_EMPTY_PATH) = 0 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f82f8d2b000 mmap(0x7f82f8d53000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f82f8d53000 mmap(0x7f82f8ee8000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7f82f8ee8000 mmap(0x7f82f8f40000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7f82f8f40000 mmap(0x7f82f8f46000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f82f8f46000 close(3) = 0 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82f8d28000 arch_prctl(ARCH_SET_FS, 0x7f82f8d28740) = 0 set_tid_address(0x7f82f8d28a10) = 11945 set_robust_list(0x7f82f8d28a20, 24) = 0 rseq(0x7f82f8d290e0, 0x20, 0, 0x53053053) = 0 mprotect(0x7f82f8f40000, 16384, PROT_READ) = 0 mprotect(0x55c85e6f4000, 4096, PROT_READ) = 0 mprotect(0x7f82f8fa3000, 8192, PROT_READ) = 0 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0 munmap(0x7f82f8f53000, 87699) = 0 getrandom("\xd5\x5d\xb9\xde\xc3\xb3\xcc\x2b", 8, GRND_NONBLOCK) = 8 brk(NULL) = 0x55c85ebe5000 brk(0x55c85ec06000) = 0x55c85ec06000 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=6784496, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 6784496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f82f86af000 close(3) = 0 newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0 write(1, "LANG=en_US.UTF-8\n", 17LANG=en_US.UTF-8 ) = 17 write(1, "LANGUAGE=\n", 10LANGUAGE= ) = 10 write(1, "LC_CTYPE=\"en_US.UTF-8\"\n", 23LC_CTYPE="en_US.UTF-8" ) = 23 write(1, "LC_NUMERIC=en_US.UTF-8\n", 23LC_NUMERIC=en_US.UTF-8 ) = 23 write(1, "LC_TIME=en_US.UTF-8\n", 20LC_TIME=en_US.UTF-8 ) = 20 write(1, "LC_COLLATE=\"en_US.UTF-8\"\n", 25LC_COLLATE="en_US.UTF-8" ) = 25 write(1, "LC_MONETARY=en_US.UTF-8\n", 24LC_MONETARY=en_US.UTF-8 ) = 24 write(1, "LC_MESSAGES=\"en_US.UTF-8\"\n", 26LC_MESSAGES="en_US.UTF-8" ) = 26 write(1, "LC_PAPER=en_US.UTF-8\n", 21LC_PAPER=en_US.UTF-8 ) = 21 write(1, "LC_NAME=en_US.UTF-8\n", 20LC_NAME=en_US.UTF-8 ) = 20 write(1, "LC_ADDRESS=en_US.UTF-8\n", 23LC_ADDRESS=en_US.UTF-8 ) = 23 write(1, "LC_TELEPHONE=en_US.UTF-8\n", 25LC_TELEPHONE=en_US.UTF-8 ) = 25 ) = 27 write(1, "LC_IDENTIFICATION=en_US.UTF-8\n", 30LC_IDENTIFICATION=en_US.UTF-8 ) = 30 write(1, "LC_ALL=\n", 8LC_ALL= ) = 8 exit_group(0) = ? +++ exited with 0 +++
Linuxのプログラムの起動と停止に関連する共通の部分と、独自の部分が見えてきます。
出力結果をファイルに保存する!
出力結果は多量になることが多いので、ファイルに出力したくなると思います。「-o」オプションで出力ファイルを指定できます。
$ strace -o strace.log locale LANG=en_US.UTF-8 LANGUAGE= LC_CTYPE="en_US.UTF-8" LC_NUMERIC=en_US.UTF-8 LC_TIME=en_US.UTF-8 LC_COLLATE="en_US.UTF-8" LC_MONETARY=en_US.UTF-8 LC_MESSAGES="en_US.UTF-8" LC_PAPER=en_US.UTF-8 LC_NAME=en_US.UTF-8 LC_ADDRESS=en_US.UTF-8 LC_TELEPHONE=en_US.UTF-8 LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=en_US.UTF-8 LC_ALL=
おわりに
straceコマンドを実行すると、使用しているシステムコールを確認することができます。いろいろ実行してみるとLinuxのプログラムの動きが見えてくると思います。
関連記事
関連書籍(Amazon)