ตัวอย่างที่เรียกใช้น้อยที่สุด
หากแนวคิดไม่ชัดเจนมีตัวอย่างที่ง่ายกว่าที่คุณไม่เคยเห็นที่อธิบาย
ในกรณีนี้ตัวอย่างนั้นเป็นชุดประกอบอิสระของ x86_64 (ไม่มี libc) สวัสดีชาวโลก:
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 ต้นน้ำ
รวบรวมและเรียกใช้:
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
บรรทัด: แสดงวิธีstrace
การดำเนินการhello.out
รวมถึงข้อโต้แย้ง CLI และสภาพแวดล้อมตามที่บันทึกไว้ที่man execve
write
บรรทัด: แสดงการเรียกของระบบการเขียนที่เราทำ คือความยาวของสตริง6
"hello\n"
= 6
คือค่าส่งคืนของการเรียกของระบบซึ่งตามที่ระบุไว้ในman 2 write
นั้นคือจำนวนไบต์ที่เขียน
exit
บรรทัด: แสดงการเรียกของระบบทางออกที่เราได้ทำ ไม่มีค่าส่งคืนเนื่องจากโปรแกรมออก!
ตัวอย่างที่ซับซ้อนมากขึ้น
แอปพลิเคชันของ strace นั้นแน่นอนว่าจะเห็นว่าระบบที่เรียกว่าโปรแกรมที่ซับซ้อนกำลังทำอะไรอยู่เพื่อช่วยแก้ไขข้อบกพร่อง / เพิ่มประสิทธิภาพโปรแกรมของคุณ
โดยเฉพาะอย่างยิ่งระบบมากที่สุดเรียกว่าคุณมีแนวโน้มที่จะพบได้ในลินุกซ์ห่อ glibc, มากของพวกเขาจาก POSIX
ภายในเครื่องห่อหุ้ม glibc ใช้ชุดประกอบแบบอินไลน์มากหรือน้อยเช่นนี้: วิธีการเรียกใช้ระบบผ่าน sysenter ในชุดประกอบแบบอินไลน์ได้อย่างไร
ตัวอย่างถัดไปที่คุณควรศึกษาคือ POSIX write
สวัสดีชาวโลก:
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
เวลานี้คุณจะเห็นว่ามีการเรียกใช้ระบบจำนวนมากโดย glibc ก่อนที่main
จะตั้งค่าสภาพแวดล้อมที่ดีสำหรับหลัก
นี่เป็นเพราะตอนนี้เราไม่ได้ใช้โปรแกรมอิสระ แต่เป็นโปรแกรม glibc ทั่วไปซึ่งช่วยให้สามารถใช้งาน libc ได้
จากนั้นที่ปลายทุกด้านstrace.log
ประกอบด้วย:
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
ดังนั้นเราจึงสรุปได้ว่าwrite
ฟังก์ชั่น POSIX ใช้, ประหลาดใจ!, การwrite
เรียกระบบLinux
นอกจากนี้เรายังสังเกตได้ว่าreturn 0
จะนำไปสู่การเรียกร้องแทนexit_group
exit
ฮาฉันไม่รู้เกี่ยวกับอันนี้! นี่คือเหตุผลที่strace
เจ๋งมาก man exit_group
จากนั้นอธิบาย:
การเรียกระบบนี้เทียบเท่ากับ exit (2) ยกเว้นว่ามันจะยุติไม่เพียง แต่การเรียกเธรดเท่านั้น แต่ยังรวมถึงเธรดทั้งหมดในกลุ่มเธรดของกระบวนการที่กำลังเรียกใช้
และนี่คืออีกตัวอย่างหนึ่งที่ฉันศึกษาว่าการเรียกdlopen
ใช้ระบบใด: /unix/226524/what-system-call-is-used-to-load-library-in-linux/466524/what-system-call-is-used-to-load-library-in-linux/462710#462710
ทดสอบใน Ubuntu 16.04, GCC 6.4.0, Linux kernel 4.4.0