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:
execvesatır: gösterileri nasıl straceidam hello.outde belgelendiği gibi CLI argümanlar ve çevre dahil olmak üzere,man execve
writeline: yaptığımız yazma sistemi çağrısını gösterir. 6dizenin uzunluğudur "hello\n".
= 6belgelendiği gibi man 2 writeyazılan bayt sayısı olan sistem çağrısının dönüş değeridir .
exitline: 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 writePOSIX işlevinin kullandığı, sürpriz !, Linuxwrite sistem çağrısı olarak
Bunun yerine return 0bir exit_groupçağrıya yol açtığını da gözlemliyoruz exit. Ha, bunu bilmiyordum! Bu yüzden straceçok havalı. man exit_groupsonra 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 dlopenkullandığı ç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.