Minimal çalıştırılabilir örnek
Bir kavram net değilse, bunu açıklayan görmediğiniz daha basit bir örnek vardır.
Bu durumda, bu örnek Linux x86_64 derleme bağımsız (libc yok) merhaba dünyasıdır:
hello.S
.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 akış yukarı .
Birleştirin ve çalıştırın:
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
Beklenen çıktılar:
hello
Şimdi bu örnek üzerinde strace kullanalım:
env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log
Kullanırız:
strace.log
şimdi içeriyor:
execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6) = 6
exit(0) = ?
+++ exited with 0 +++
Böyle minimal bir örnekle, çıktının her bir karakteri kendini belli eder:
execve
satır: gösterileri nasıl strace
idam hello.out
de belgelendiği gibi CLI argümanlar ve çevre dahil olmak üzere,man execve
write
line: yaptığımız yazma sistemi çağrısını gösterir. 6
dizenin uzunluğudur "hello\n"
.
= 6
belgelendiği gibi man 2 write
yazılan bayt sayısı olan sistem çağrısının dönüş değeridir .
exit
line: yaptığımız çıkış sistemi çağrısını gösterir. Programdan çıkıldığı için dönüş değeri yoktur!
Daha karmaşık örnekler
Strace uygulaması elbette programınızın hatalarını ayıklamak / optimize etmek için karmaşık programların gerçekte hangi sistem çağrılarını yaptığını görmektir.
Özellikle, Linux'ta karşılaşma olasılığı çoğu sistem çağrıları, glibc sarmalayıcılarını var POSIX birçoğu .
Dahili olarak, glibc sarmalayıcıları satır içi montajı aşağıdaki gibi kullanır: şöyle kullanır: Satır içi montajda sysenter aracılığıyla bir sistem çağrısı nasıl çağrılır?
Çalışmanız gereken bir sonraki örnek POSIX write
merhaba dünyası:
main.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
char *msg = "hello\n";
write(1, msg, 6);
return 0;
}
Derleyin ve çalıştırın:
gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
Bu sefer glibc tarafından daha önce bir grup sistem çağrısı yapıldığını göreceksiniz. main
main için güzel bir ortam .
Çünkü artık bağımsız bir program değil, libc işlevselliğine izin veren daha yaygın bir glibc programı kullanıyoruz.
Ardından, her iki uçta strace.log
şunları içerir:
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
Bu yüzden write
POSIX işlevinin kullandığı, sürpriz !, Linuxwrite
sistem çağrısı olarak
Bunun yerine return 0
bir exit_group
çağrıya yol açtığını da gözlemliyoruz exit
. Ha, bunu bilmiyordum! Bu yüzden strace
çok havalı. man exit_group
sonra açıklar:
Bu sistem çağrısı, yalnızca çağıran iş parçacığını değil, çağıran işlemin iş parçacığı grubundaki tüm iş parçacıklarını sonlandırması dışında exit (2) öğesine eşdeğerdir.
Ve hangi sistem çağrısının dlopen
kullandığı çalıştığım başka bir örnek : /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710
Ubuntu 16.04, GCC 6.4.0, Linux çekirdeği 4.4.0'da test edilmiştir.