न्यूनतम रननीय उदाहरण
यदि कोई अवधारणा स्पष्ट नहीं है, तो एक सरल उदाहरण है जो आपने नहीं देखा है जो इसे बताता है।
इस मामले में, वह उदाहरण लिनक्स 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 +++
तो हम निष्कर्ष निकालते हैं कि writePOSIX फ़ंक्शन उपयोग करता है, आश्चर्य!, लिनक्स 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 में परीक्षण किया गया।