最小限の実行可能な例
概念が明確でない場合は、それを説明する、見たことのない簡単な例があります。
この場合、その例はLinux x86_64アセンブリの自立型(libcなし)hello worldです。
こんにちは。
.text
.global _start
_start:
/* write */
mov $1, %rax /* syscall number */
mov $1, %rdi /* stdout */
mov $msg, %rsi /* buffer */
mov $len, %rdx /* buffer len */
syscall
/* exit */
mov $60, %rax /* exit status */
mov $0, %rdi /* syscall number */
syscall
msg:
.ascii "hello\n"
len = . - msg
GitHubアップストリーム。
組み立てて実行する:
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
期待される出力:
hello
次に、その例でstraceを使用します。
env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log
を使用しております:
strace.log
今が含まれています:
execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6) = 6
exit(0) = ?
+++ exited with 0 +++
そのような最小限の例では、出力のすべての文字は自明です。
execve
行:CLI引数と環境を含む、strace
実行方法を示します。hello.out
man execve
write
line:作成した書き込みシステムコールを示します。6
文字列の長さです"hello\n"
。
= 6
記載されてman 2 write
いるように、書き込まれたバイト数であるシステムコールの戻り値です。
exit
line:実行したexitシステムコールを示します。プログラムが終了したため、戻り値はありません。
より複雑な例
straceの適用はもちろん、プログラムのデバッグ/最適化を支援するために複雑なプログラムが実際に実行しているシステムコールを確認することです。
特に、Linuxで遭遇する可能性が高いほとんどのシステムコールにはglibcラッパーがあり、その多くはPOSIXからのものです。
内部的には、glibcラッパーは多かれ少なかれ次のようにインラインアセンブリを使用します:インラインアセンブリでsysenterを介してシステムコールを呼び出す方法は?
次の例は、POSIX write
hello worldです。
main.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
char *msg = "hello\n";
write(1, msg, 6);
return 0;
}
コンパイルして実行:
gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
今回はmain
、mainの適切な環境をセットアップする前に、glibcによって一連のシステムコールが行われていることがわかります。
これは、現在、独立したプログラムではなく、libc機能を可能にする、より一般的なglibcプログラムを使用しているためです。
次に、両端に以下strace.log
が含まれます。
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
したがって、write
POSIX関数がLinux write
システムコールを使用していると結論付けました。
またreturn 0
、exit_group
ではなく呼び出しが発生することもわかりexit
ます。あ、これは知らなかった!これがstrace
とてもクールな理由です。man exit_group
次に説明します:
このシステムコールは、呼び出しスレッドだけでなく、呼び出しプロセスのスレッドグループ内のすべてのスレッドを終了することを除いて、exit(2)と同等です。
そして、これは私がどのシステムコールがdlopen
使用するかを調べた別の例です:https : //unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710
Ubuntu 16.04、GCC 6.4.0、Linuxカーネル4.4.0でテスト済み。