न्यूनतम रननीय उदाहरण
Brk () सिस्टम कॉल क्या करता है?
गिरी को बताता है कि आप उसे पढ़ने और लिखने के लिए स्मृति के एक सन्निहित भाग को लिखते हैं जिसे ढेर कहा जाता है।
यदि आप नहीं पूछते हैं, तो यह आपको अलग कर सकता है।
इसके बिना brk
:
#define _GNU_SOURCE
#include <unistd.h>
int main(void) {
/* Get the first address beyond the end of the heap. */
void *b = sbrk(0);
int *p = (int *)b;
/* May segfault because it is outside of the heap. */
*p = 1;
return 0;
}
के साथ brk
:
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b = sbrk(0);
int *p = (int *)b;
/* Move it 2 ints forward */
brk(p + 2);
/* Use the ints. */
*p = 1;
*(p + 1) = 2;
assert(*p == 1);
assert(*(p + 1) == 2);
/* Deallocate back. */
brk(b);
return 0;
}
गिटहब ऊपर ।
उपरोक्त एक नया पृष्ठ हिट नहीं हो सकता है और बिना सीगफॉल्ट के भी नहीं हो सकता है brk
, इसलिए यहां एक अधिक आक्रामक संस्करण है जो 16MiB आवंटित करता है और इसके बिना सीगफॉल्ट की संभावना है brk
:
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b;
char *p, *end;
b = sbrk(0);
p = (char *)b;
end = p + 0x1000000;
brk(end);
while (p < end) {
*(p++) = 1;
}
brk(b);
return 0;
}
उबंटू 18.04 पर परीक्षण किया गया।
वर्चुअल एड्रेस स्पेस विज़ुअलाइज़ेशन
इससे पहले brk
:
+------+ <-- Heap Start == Heap End
के बाद brk(p + 2)
:
+------+ <-- Heap Start + 2 * sizof(int) == Heap End
| |
| You can now write your ints
| in this memory area.
| |
+------+ <-- Heap Start
के बाद brk(b)
:
+------+ <-- Heap Start == Heap End
एड्रेस स्पेस को बेहतर तरीके से समझने के लिए, आपको पेजिंग से खुद को परिचित करना चाहिए: x86 पेजिंग कैसे काम करता है?।
हम क्यों की जरूरत है दोनों करते हैं brk
और sbrk
?
brk
के साथ लागू किया जा सकता है sbrk
+ ऑफसेट गणना के , दोनों सिर्फ सुविधा के लिए मौजूद हैं।
बैकएंड में, लिनक्स कर्नेल v5.0 में एक सिंगल सिस्टम कॉल brk
है जिसका उपयोग दोनों को लागू करने के लिए किया जाता है: https://github.com/torvalds/linux/blob/v5.0/arch/x86/entry/syscalls_syscall_64। tbl # L23
12 common brk __x64_sys_brk
है brk
POSIX?
brk
POSIX हुआ करता था, लेकिन POSIX 2001 में इसे हटा दिया गया, इस प्रकार इसकी आवश्यकता थी _GNU_SOURCE
ग्लिबक रैपर तक पहुंचने की ।
परिचय के कारण हटाने की संभावना है mmap
, जो एक सुपरसेट है जो कई रेंज को आवंटित करने और अधिक आवंटन विकल्प की अनुमति देता है।
मुझे लगता है कि कोई वैध मामला नहीं है जहां आपको brk
इसके बजाय malloc
या mmap
आजकल का उपयोग करना चाहिए ।
brk
बनाम malloc
brk
लागू करने की एक पुरानी संभावना है malloc
।
mmap
वर्तमान में लागू करने के लिए वर्तमान में उपयोग किए जाने वाले सभी POSIX सिस्टम की संभावना नए शक्तिशाली रूप से अधिक शक्तिशाली तंत्र है malloc
। यहाँ एक न्यूनतम रननेबल mmap
मेमोरी आवंटन उदाहरण है ।
क्या मैं मिश्रण brk
और मालॉक कर सकता हूं ?
यदि आपके malloc
साथ कार्यान्वित किया जाता है brk
, तो मुझे पता नहीं है कि कैसे संभवत: चीजों को उड़ा नहीं सकता है, क्योंकि brk
केवल स्मृति की एक सीमा होती है।
हालाँकि मुझे इसके बारे में कुछ भी पता नहीं चल पाया है, उदाहरण के लिए:
चीजें संभवत: वहीं काम करेंगी जो मुझे लगता है mmap
कि संभावना है malloc
।
यह सभी देखें:
और जानकारी
आंतरिक रूप से, कर्नेल यह तय करता है कि क्या इस प्रक्रिया में बहुत अधिक मेमोरी और इयरमार्क्स मेमोरी पेज हो सकते हैं उस उपयोग के लिए ।
यह बताता है कि ढेर की तुलना कैसे की जाती है: x86 असेंबली में रजिस्टरों पर उपयोग किए जाने वाले पुश / पॉप निर्देशों का क्या कार्य है?