न्यूनतम रननीय उदाहरण
यदि कोई अवधारणा स्पष्ट नहीं है, तो एक सरल उदाहरण है जो आपने नहीं देखा है जो इसे बताता है।
इस मामले में, वह उदाहरण लिनक्स x86_64 असेंबली फ्रीस्टैंडिंग (कोई लिबास) हैलो दुनिया नहीं है:
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
गिटहब ऊपर ।
इकट्ठा करें और चलाएं:
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
अपेक्षित आउटपुट:
hello
अब उस उदाहरण पर स्ट्रेस का उपयोग करते हैं:
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
, जिसमें सीएलआई तर्क और पर्यावरण शामिल हैंman execve
write
पंक्ति: हम लिखी गई कॉल सिस्टम को दिखाते हैं। 6
स्ट्रिंग की लंबाई है "hello\n"
।
= 6
सिस्टम कॉल का रिटर्न मान है, जिसे दस्तावेज के रूप में man 2 write
लिखा गया बाइट्स की संख्या है।
exit
पंक्ति: हमारे द्वारा किए गए निकास प्रणाली कॉल को दिखाता है। कार्यक्रम छोड़ने के बाद से कोई वापसी मूल्य नहीं है!
अधिक जटिल उदाहरण
स्ट्रेस का अनुप्रयोग निश्चित रूप से यह देखने के लिए है कि कौन से सिस्टम कॉल जटिल प्रोग्राम वास्तव में डिबग / आपके प्रोग्राम को ऑप्टिमाइज़ करने में मदद करते हैं।
विशेष रूप से, अधिकांश सिस्टम कॉल जो आपको लिनक्स में मुठभेड़ की संभावना रखते हैं, ग्लिबक रैपर हैं, उनमें से कई पॉसिक्स से हैं ।
आंतरिक रूप से, ग्लिब रैपर इनलाइन असेंबली का कम या ज्यादा उपयोग करते हैं: इनलाइन असेंबली में सिसेंटर के माध्यम से सिस्टम कॉल कैसे करें?
अगला उदाहरण जो आपको अध्ययन करना चाहिए, वह है 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
इस बार, आप देखेंगे कि main
मुख्य के लिए एक अच्छा वातावरण सेटअप करने से पहले glibc द्वारा सिस्टम कॉल का एक गुच्छा बनाया जा रहा है ।
ऐसा इसलिए है क्योंकि अब हम एक फ्रीस्टैंडिंग प्रोग्राम का उपयोग नहीं कर रहे हैं, बल्कि एक अधिक सामान्य ग्लिबक प्रोग्राम है, जो लिबास कार्यक्षमता के लिए अनुमति देता है।
फिर, हर छोर पर, strace.log
शामिल हैं:
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
तो हम निष्कर्ष निकालते हैं कि write
POSIX फ़ंक्शन उपयोग करता है, आश्चर्य!, लिनक्स write
सिस्टम कॉल।
हम यह भी मानते हैं कि इसके बजाय return 0
एक exit_group
कॉल होता है exit
। हा, मैं इस बारे में नहीं जानता था! यही कारण है कि strace
बहुत अच्छा है। man exit_group
फिर बताते हैं:
यह सिस्टम कॉल बाहर निकलने के बराबर है (2) सिवाय इसके कि यह न केवल कॉलिंग थ्रेड को समाप्त करता है, बल्कि कॉलिंग प्रक्रिया के थ्रेड समूह में सभी थ्रेड्स को समाप्त करता है।
और यहाँ एक और उदाहरण है जहाँ मैंने अध्ययन किया कि कौन सी प्रणाली कॉल dlopen
का उपयोग करती है: /unix/226524/what-system-call-is-used-to-load-lbooks-in-linux-462710#462710
उबंटू 16.04, जीसीसी 6.4.0, लिनक्स कर्नेल 4.4.0 में परीक्षण किया गया।