ตัวอย่างที่เรียกใช้น้อยที่สุด
หากแนวคิดไม่ชัดเจนมีตัวอย่างที่ง่ายกว่าที่คุณไม่เคยเห็นที่อธิบาย
ในกรณีนี้ตัวอย่างนั้นเป็นชุดประกอบอิสระของ 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